Pharo-dev
By thread
pharo-dev@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
April 2016
- 843 messages
Re: [Pharo-dev] [ bloc ] I do not understand why some behavior is not in the right place
by Igor Stasenko
On 5 April 2016 at 16:15, Aliaksei Syrel <alex.syrel(a)gmail.com> wrote:
> Hello Igor
>
> Thanks for extensive design explanation and effort!
> Issues you mentioned in previous emails are important and need to be
> addressed :)
> fill(), stroke() fillPreserve() strokePreserve() need to disappear in the
> end. We will come back to them later.
>
> /me feel happiness :)
> Let me tell a few words about Sparta.
> Sparta implements Athens interface api (excluding some experimental stuff
> to test possible performance boost in a few places) and does not have task
> to remove Athens style and abstractions. Ideally Sparta will be AthensCairo
> for bloc. I'm looking forward for your help :)
>
> Here are some aspects in AthensCairo that Sparta tries to address in first
> place:
>
> - *Clipping in local coordinates*. It is critical in Bloc. You
> implemented AthensCairo to have vector based rendering in Morphic and Pharo
> in general. Morphic lives in global coordinates, so your choice to clip in
> global coordinate is perfect! At the same time global clipping in bloc adds
> complexity. Sparta clips always in local coordinates (user space in cairo
> terminology).
>
> No, my code is not perfect. Don't say it like that. It was just a mere
attempt to marry Morphic with Athens, in order to make things work.. But if
it works, it doesn't means it perfect. It just works. I don't need false
credit(s) :)
Ideally , of course, all clipping should be done in local coordinates.
There should be no, or as little as possible things, that require absolute
coordinates. And so, i am happy to hear that, and that we are on same side
here, i can only welcome any steps towards that direction.
>
> - *Clip by arbitrary path*. Athens and AthenCairo expect to see
> aRectangle as clipping region - your wise choice for morphic. In bloc I
> would have clipping by arbitrary path. clipBy:during: gets aPath.
> Rectangle/Color is polymorphic with path/paint in Sparta
>
> That is also a step forward. Ideally it should be possible in Athens as
well, to clip using any shape. But.. yeah.. we needed to implement simplest
things first, before introducing more.
So, ideally what you need is to extend functionality of
#clipBy:during: , of AthensCanvas, and allow any shape, not just Rectangle.
> - *Support of groups*. (maybe user-level aspect? like shadows) Groups
> are powerful in cairo (do they exist outside of cairo?) and allow to draw
> both transparent fill and stroke without overlapping using only one path.
> On class side of BlElement there are examples (exampleCircle) that show
> such behavior.
>
> Hmm.. That is a higher level/dimension concept. I doubt that graphics
engine needs to support it out of the box.
Grouping operations is up to the user.. there's no single fixed way how one
can group simple operations of fill() function.. and in what order whatever.
I do not object that grouping operations are not useful. I just objecting
that it should be part of core API.
Any kind of grouping is allowed at the user level, so in Bloc you are free
to introduce it the way you like or want.
I would say more about it, if you would motivate , what you can see, how
graphical engine could potentially allow better performance/ease of use in
case if it will support groups.
For instance , in OpenGL there are a command lists, which you can compile
once and then execute it as many time as you want. That is useful in terms
that it can prepare a bunch of operations and optimize them for later use.
This is basically a simple command pattern, implemented in C :)
>From that perspective, if you mean support of groups in that way.. then it
is good direction. But if not, then i am not convinced.
> - *Do not maintain and set pathTransformation before each
> render-dependent action.* Questionable but what if Canvas will not
> maintain current state of pathTransform? Instead all transformations can be
> directly applied on cairo_t using native calls. If there is a need to get
> actual matrix we can ask cairo directly. From my perspective it simplifies
> transformation stuff a little bit.
>
> Review and optimization. I can only welcome that.
>
> - *Benefit from cairo_save and cairo_restore.* AthensCairo maintains
> state manually by setting transformation matrix and clip. Instead we could
> save and restore state without caring about clip/matrix which simplifies
> code. Check SpartaCanvas>>#clipBy:during:
>
> Sure, using backend to its full potential is again can be only welcomed.
But Cairo is not the only backend for Athens.
So, if you can expose such operation at more backend neutral level in
Athens, then it is welcome as well.
I was thinking about that, but never got my hands to it.. How to expose it
in backend-neutral way.
So, if you found how - do it. I can only welcome that.
> Cheers,
> Alex
>
> On Tue, Apr 5, 2016 at 2:12 PM, Igor Stasenko <siguctua(a)gmail.com> wrote:
>
>>
>> Couple more words about that fill() function abstraction.
>> Now you probably understand why there's no notion of stroke operation in
>> Athens.
>> Because instead of introducing it that way, by adding new kind of a
>> function
>> stroke(shape,paint)
>> from our perspective, it falls into our more generic fill() function,
>> except that
>> instead of literally filling the shape we deciding to paint a stroke:
>> fill(shape, strokePaint).
>>
>> As i said, there's nothing that tells that fill() function must affect
>> only areas enclosed by the shape.
>> For instance, you could imagine, that i'm in contrary, may want to fill
>> everything , but the area(s) enclosed by given shape. And that still can be
>> represented as invocation of our generic fill() function, except that we
>> will use a different kind of paint, that will fill everything outside
>> designated region, i.e.:
>> fill(shape, fillOutsidePaint)
>>
>>
>>
>> On 5 April 2016 at 14:33, Igor Stasenko <siguctua(a)gmail.com> wrote:
>>
>>>
>>>
>>> On 5 April 2016 at 04:00, Ben Coman <btc(a)openinworld.com> wrote:
>>>
>>>> On Tue, Apr 5, 2016 at 2:51 AM, Igor Stasenko <siguctua(a)gmail.com>
>>>> wrote:
>>>> >
>>>> > Some more bashing today.. (don't take it personal, i may be wrong)
>>>> >
>>>> > BlPath hierarchy.. and BlShape.
>>>> >
>>>> > Why you redefining what is shape and what is path?
>>>> > Of course, you are free to do it in Bloc..
>>>> > But in terms of Athens, all of BlPath are actually - shapes..
>>>> > And BlShape is some kind of encapsulation of shape, paints and
>>>> transform.
>>>> > It is a dumb state holder without any extra logic.
>>>> >
>>>> > My rule of thumb: do not produce dumb state holders. They has to be
>>>> smart,
>>>> > else it makes no sense in creating separate entity and designating it
>>>> as
>>>> > something else than any other bunch of data thrown into single clump,
>>>> > sitting there deaf, blind, dead and silent until someone else will
>>>> grab it
>>>> > somewhere
>>>> > and start using it for own purpose.
>>>> >
>>>> > Sure, i could understand, why you potentially may want such object(s)
>>>> > around,
>>>> > but it is not shape anymore and i wouldn't call it like that. Because
>>>> shape
>>>> > are shape, and has nothing to do with paints and transform,
>>>> > it don't knows and don't cares whether it will be filled or stroked
>>>> or both,
>>>> > and how many times, and if there will be single paint or thousand.
>>>> > Such kind of properties is simply orthogonal to what shape existing
>>>> for,
>>>> > because it exists only to define geometry.
>>>> >
>>>> > I think all of that came from not understanding the roles of objects
>>>> and how
>>>> > they interact in Athens.
>>>>
>>>> Can you point us to documentation that describes Athen's architecture
>>>> for these interactions?
>>>> (sorry I haven't checked class comments, but I'm looking to start with
>>>> something at higher level anyway)
>>>>
>>>
>>> No, i can't point it out. And you are right , this is nobody else's
>>> fault than my own. I feel ashamed. Sure how i could demand that people
>>> understand the concepts, if i didn't explained then anywhere (or if i did,
>>> it is not in easily reachable place).
>>>
>>> So, lets fix that. I will write it down here, and you can pick it up and
>>> find suitable place for it.
>>>
>>> ----------
>>> Basic abstractions behind Athens.
>>>
>>> Since Athens is about drawing graphics, we need a media where all
>>> drawing operations will appear. We call that media a surface.
>>> The surface is abstract. It can have set dimensions, or don't. We don't
>>> define if it representing some kind of physical surface (like part of the
>>> display screen), or how it storing the data inside. We leaving an
>>> introduction of such details to concrete surface implementation.
>>> All that matters is that surface is a final target of all our drawing
>>> operations.
>>> Therefore, in Athens, a surface is usually a starting point where all
>>> begins from, and you doing so by creating a specific surface.
>>> It is surface's responsibility then, to provide user a means how he can
>>> draw on it, and therefore there is a number of factory methods, that
>>> allowing you to create a canvas, paints and shapes. All those three are
>>> specific implementation of AthensCanvas, AthensPaint and AthensShape
>>> protocols, suitable to be used with specific surface implementation that
>>> you using.
>>>
>>> Canvas.
>>> Canvas represents a basic drawing context. We don't allow a direct
>>> operations with surface, but instead we provide a context, that contains
>>> and carries all information that represents a current stage of drawing
>>> operations.
>>> This includes things like, current coordinate transformation(s),
>>> currently selected paint and shape, and paint mode.
>>>
>>> In order to obtain canvas, one must use #drawDuring: message sent to
>>> surface with block as argument. The given block receives an instance of
>>> AthensCanvas as a single parameter. We intentionally enclosing all possible
>>> drawing operations within a block to make sure that when we leave, we can
>>> safely release all resources that was allocated, required to hold the
>>> drawing context state. By exposing it in such form, we also making sure
>>> that nothing can alter the surface outside a given block. That way, it
>>> gives users a definitive answer, whether he finished drawing operations or
>>> not, and if it safe to operate with surface for things like saving it to
>>> file, or using it as a source for more complex operations, like acting as a
>>> paint to fill area(s) inside another surface etc.
>>>
>>> Paints and shapes.
>>> A starting point is answering a question, how we can represent a
>>> simplest, elementary drawing operation on a surface without putting too
>>> much constraints.
>>> We doing so by postulating that any elementary drawing operation can be
>>> expressed by a function:
>>>
>>> fill(paint, shape)
>>>
>>> Please, note that 'fill' here is not a literally fill given shape with
>>> given paint. We call it 'fill' for simplicity reason. It can anything that
>>> altering the surface, but always taking into account given parameters:
>>> paint and shape.
>>>
>>> Then, from that perspective we can clearly say what are the roles and
>>> responsibility of shapes and paints.
>>>
>>> The shape defines the affected region, its geometry and location,
>>> while paint defines how that region will be altered.
>>> In this way, most of more complex operations can be expressed as a
>>> series of such function invocations by using various paints and shapes.
>>>
>>> Such representation also gives us a minimal set of roles, a building
>>> bricks, that we need to introduce in order to represent any kind of drawing
>>> operation we may need, as well as a minimal functionality in order to
>>> implement such function(s). And therefore a minimal protocol(s), that all
>>> paints and shapes should implement.
>>>
>>> Since there potentially infinite number of various paint kinds and shape
>>> kinds, we cannot make a single function that will implement all possible
>>> permutations in order to fill shape with concrete paint.
>>> To solve that we introducing a straight dispatch mechanism, where we
>>> delegate the responsibility of implementing a concrete case, first to
>>> shape, and then to paint.
>>>
>>> The API representing this function in canvas by #draw protocol.
>>> It takes currently selected paint and currently selected shape and
>>> starting dispatch:
>>>
>>> draw
>>> "Fill the currently selected shape with currently selected paint"
>>> ^ shape paintFillsUsing: paint on: self
>>>
>>> So, first it goes to the shape, by sending #paintFillsUsing:on: ,
>>> then shape dispatching it further to paint by sending appropriate message
>>> (be it #athensFillPath:on: or #athensFillRectangle:on: or anything else,
>>> if you want to introduce new kind of shape representation and implement it
>>> accordingly).
>>> Such dispatch gives us an ability to easily extend the framework by
>>> introducing new kind of shapes and paints , by implementing new kind of
>>> fill() functions for them.
>>>
>>> -----------
>>>
>>> I hope that will make clear at least part of things what is there,
>>> behind the scenes.
>>>
>>>
>>>> cheers -ben
>>>>
>>>>
>>>
>>> --
>>> Best regards,
>>> Igor Stasenko.
>>>
>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko.
>>
>
>
--
Best regards,
Igor Stasenko.
April 5, 2016
Re: [Pharo-dev] Pharo Days 2016 Photos and Video
by Tudor Girba
Nice :)
Cheers,
Tudor
> On Apr 4, 2016, at 12:15 AM, Yuriy Tymchuk <yuriy.tymchuk(a)me.com> wrote:
>
> Good morning everyone!
>
> I think that itâs a nice way to start the new week by viewing photos from Pharo Days 2016: https://goo.gl/photos/orgTn4C1bSeqf6fy5.
> Additionally if someone wants to get a quick impression of the conference, now there is a video for that: https://youtu.be/eHKtxgbuLSg.
>
>
> Have a great week.
> Cheers!
> Uko
--
www.tudorgirba.com
www.feenk.com
"When people care, great things can happen."
April 5, 2016
Re: [Pharo-dev] [ bloc ] I do not understand why some behavior is not in the right place
by Aliaksei Syrel
Now let's take a look at this code:
drawOnSpartaCanvas: aCanvas
> aCanvas
> clipPreserveBy: self shape during: [
> aCanvas paintGroup: [
> aCanvas setPaint: self shape fillPaint.
> aCanvas fillPreserve.
> aCanvas paintMode source.
> aCanvas setStrokePaint: self shape strokePaint.
> aCanvas stroke ] ]
You may be curious why it is so ugly :) Make it work - make it right - make
it fast. We are on the first etappe, because I invested zero time in
rendering stuff.
What you see is the minimal amount of cairo primitive calls that are needed
to render not overlapping fill and stroke. Clipping is needed to make sure
that stroke does not get rendered outside of a path. Group is needed to
have transparent target in order to make source paint mode work as
expected. Compared to image_surface group, it in this case allows to
preserve clip and current cairo state which is pushed to stack during
push_group and restored during pop_group_to_source. fillPreserve allows to
reuse the same path as used for clipping before saving cpu time on loading
path.
It is implemented in canvas specific method after dispatch though canvas,
so we are allowed to use canvas specific api, for example groups.
How to model stroke, fillPreserve and paintModein terms of Athens?
Cheers,
Alex
On Tue, Apr 5, 2016 at 3:15 PM, Aliaksei Syrel <alex.syrel(a)gmail.com> wrote:
> Hello Igor
>
> Thanks for extensive design explanation and effort!
> Issues you mentioned in previous emails are important and need to be
> addressed :)
> fill(), stroke() fillPreserve() strokePreserve() need to disappear in the
> end. We will come back to them later.
>
> Let me tell a few words about Sparta.
> Sparta implements Athens interface api (excluding some experimental stuff
> to test possible performance boost in a few places) and does not have task
> to remove Athens style and abstractions. Ideally Sparta will be AthensCairo
> for bloc. I'm looking forward for your help :)
>
> Here are some aspects in AthensCairo that Sparta tries to address in first
> place:
>
> - *Clipping in local coordinates*. It is critical in Bloc. You
> implemented AthensCairo to have vector based rendering in Morphic and Pharo
> in general. Morphic lives in global coordinates, so your choice to clip in
> global coordinate is perfect! At the same time global clipping in bloc adds
> complexity. Sparta clips always in local coordinates (user space in cairo
> terminology).
> - *Clip by arbitrary path*. Athens and AthenCairo expect to see
> aRectangle as clipping region - your wise choice for morphic. In bloc I
> would have clipping by arbitrary path. clipBy:during: gets aPath.
> Rectangle/Color is polymorphic with path/paint in Sparta
> - *Support of groups*. (maybe user-level aspect? like shadows) Groups
> are powerful in cairo (do they exist outside of cairo?) and allow to draw
> both transparent fill and stroke without overlapping using only one path.
> On class side of BlElement there are examples (exampleCircle) that show
> such behavior.
> - *Do not maintain and set pathTransformation before each
> render-dependent action.* Questionable but what if Canvas will not
> maintain current state of pathTransform? Instead all transformations can be
> directly applied on cairo_t using native calls. If there is a need to get
> actual matrix we can ask cairo directly. From my perspective it simplifies
> transformation stuff a little bit.
> - *Benefit from cairo_save and cairo_restore.* AthensCairo maintains
> state manually by setting transformation matrix and clip. Instead we could
> save and restore state without caring about clip/matrix which simplifies
> code. Check SpartaCanvas>>#clipBy:during:
>
>
> Cheers,
> Alex
>
> On Tue, Apr 5, 2016 at 2:12 PM, Igor Stasenko <siguctua(a)gmail.com> wrote:
>
>>
>> Couple more words about that fill() function abstraction.
>> Now you probably understand why there's no notion of stroke operation in
>> Athens.
>> Because instead of introducing it that way, by adding new kind of a
>> function
>> stroke(shape,paint)
>> from our perspective, it falls into our more generic fill() function,
>> except that
>> instead of literally filling the shape we deciding to paint a stroke:
>> fill(shape, strokePaint).
>>
>> As i said, there's nothing that tells that fill() function must affect
>> only areas enclosed by the shape.
>> For instance, you could imagine, that i'm in contrary, may want to fill
>> everything , but the area(s) enclosed by given shape. And that still can be
>> represented as invocation of our generic fill() function, except that we
>> will use a different kind of paint, that will fill everything outside
>> designated region, i.e.:
>> fill(shape, fillOutsidePaint)
>>
>>
>>
>> On 5 April 2016 at 14:33, Igor Stasenko <siguctua(a)gmail.com> wrote:
>>
>>>
>>>
>>> On 5 April 2016 at 04:00, Ben Coman <btc(a)openinworld.com> wrote:
>>>
>>>> On Tue, Apr 5, 2016 at 2:51 AM, Igor Stasenko <siguctua(a)gmail.com>
>>>> wrote:
>>>> >
>>>> > Some more bashing today.. (don't take it personal, i may be wrong)
>>>> >
>>>> > BlPath hierarchy.. and BlShape.
>>>> >
>>>> > Why you redefining what is shape and what is path?
>>>> > Of course, you are free to do it in Bloc..
>>>> > But in terms of Athens, all of BlPath are actually - shapes..
>>>> > And BlShape is some kind of encapsulation of shape, paints and
>>>> transform.
>>>> > It is a dumb state holder without any extra logic.
>>>> >
>>>> > My rule of thumb: do not produce dumb state holders. They has to be
>>>> smart,
>>>> > else it makes no sense in creating separate entity and designating it
>>>> as
>>>> > something else than any other bunch of data thrown into single clump,
>>>> > sitting there deaf, blind, dead and silent until someone else will
>>>> grab it
>>>> > somewhere
>>>> > and start using it for own purpose.
>>>> >
>>>> > Sure, i could understand, why you potentially may want such object(s)
>>>> > around,
>>>> > but it is not shape anymore and i wouldn't call it like that. Because
>>>> shape
>>>> > are shape, and has nothing to do with paints and transform,
>>>> > it don't knows and don't cares whether it will be filled or stroked
>>>> or both,
>>>> > and how many times, and if there will be single paint or thousand.
>>>> > Such kind of properties is simply orthogonal to what shape existing
>>>> for,
>>>> > because it exists only to define geometry.
>>>> >
>>>> > I think all of that came from not understanding the roles of objects
>>>> and how
>>>> > they interact in Athens.
>>>>
>>>> Can you point us to documentation that describes Athen's architecture
>>>> for these interactions?
>>>> (sorry I haven't checked class comments, but I'm looking to start with
>>>> something at higher level anyway)
>>>>
>>>
>>> No, i can't point it out. And you are right , this is nobody else's
>>> fault than my own. I feel ashamed. Sure how i could demand that people
>>> understand the concepts, if i didn't explained then anywhere (or if i did,
>>> it is not in easily reachable place).
>>>
>>> So, lets fix that. I will write it down here, and you can pick it up and
>>> find suitable place for it.
>>>
>>> ----------
>>> Basic abstractions behind Athens.
>>>
>>> Since Athens is about drawing graphics, we need a media where all
>>> drawing operations will appear. We call that media a surface.
>>> The surface is abstract. It can have set dimensions, or don't. We don't
>>> define if it representing some kind of physical surface (like part of the
>>> display screen), or how it storing the data inside. We leaving an
>>> introduction of such details to concrete surface implementation.
>>> All that matters is that surface is a final target of all our drawing
>>> operations.
>>> Therefore, in Athens, a surface is usually a starting point where all
>>> begins from, and you doing so by creating a specific surface.
>>> It is surface's responsibility then, to provide user a means how he can
>>> draw on it, and therefore there is a number of factory methods, that
>>> allowing you to create a canvas, paints and shapes. All those three are
>>> specific implementation of AthensCanvas, AthensPaint and AthensShape
>>> protocols, suitable to be used with specific surface implementation that
>>> you using.
>>>
>>> Canvas.
>>> Canvas represents a basic drawing context. We don't allow a direct
>>> operations with surface, but instead we provide a context, that contains
>>> and carries all information that represents a current stage of drawing
>>> operations.
>>> This includes things like, current coordinate transformation(s),
>>> currently selected paint and shape, and paint mode.
>>>
>>> In order to obtain canvas, one must use #drawDuring: message sent to
>>> surface with block as argument. The given block receives an instance of
>>> AthensCanvas as a single parameter. We intentionally enclosing all possible
>>> drawing operations within a block to make sure that when we leave, we can
>>> safely release all resources that was allocated, required to hold the
>>> drawing context state. By exposing it in such form, we also making sure
>>> that nothing can alter the surface outside a given block. That way, it
>>> gives users a definitive answer, whether he finished drawing operations or
>>> not, and if it safe to operate with surface for things like saving it to
>>> file, or using it as a source for more complex operations, like acting as a
>>> paint to fill area(s) inside another surface etc.
>>>
>>> Paints and shapes.
>>> A starting point is answering a question, how we can represent a
>>> simplest, elementary drawing operation on a surface without putting too
>>> much constraints.
>>> We doing so by postulating that any elementary drawing operation can be
>>> expressed by a function:
>>>
>>> fill(paint, shape)
>>>
>>> Please, note that 'fill' here is not a literally fill given shape with
>>> given paint. We call it 'fill' for simplicity reason. It can anything that
>>> altering the surface, but always taking into account given parameters:
>>> paint and shape.
>>>
>>> Then, from that perspective we can clearly say what are the roles and
>>> responsibility of shapes and paints.
>>>
>>> The shape defines the affected region, its geometry and location,
>>> while paint defines how that region will be altered.
>>> In this way, most of more complex operations can be expressed as a
>>> series of such function invocations by using various paints and shapes.
>>>
>>> Such representation also gives us a minimal set of roles, a building
>>> bricks, that we need to introduce in order to represent any kind of drawing
>>> operation we may need, as well as a minimal functionality in order to
>>> implement such function(s). And therefore a minimal protocol(s), that all
>>> paints and shapes should implement.
>>>
>>> Since there potentially infinite number of various paint kinds and shape
>>> kinds, we cannot make a single function that will implement all possible
>>> permutations in order to fill shape with concrete paint.
>>> To solve that we introducing a straight dispatch mechanism, where we
>>> delegate the responsibility of implementing a concrete case, first to
>>> shape, and then to paint.
>>>
>>> The API representing this function in canvas by #draw protocol.
>>> It takes currently selected paint and currently selected shape and
>>> starting dispatch:
>>>
>>> draw
>>> "Fill the currently selected shape with currently selected paint"
>>> ^ shape paintFillsUsing: paint on: self
>>>
>>> So, first it goes to the shape, by sending #paintFillsUsing:on: ,
>>> then shape dispatching it further to paint by sending appropriate message
>>> (be it #athensFillPath:on: or #athensFillRectangle:on: or anything else,
>>> if you want to introduce new kind of shape representation and implement it
>>> accordingly).
>>> Such dispatch gives us an ability to easily extend the framework by
>>> introducing new kind of shapes and paints , by implementing new kind of
>>> fill() functions for them.
>>>
>>> -----------
>>>
>>> I hope that will make clear at least part of things what is there,
>>> behind the scenes.
>>>
>>>
>>>> cheers -ben
>>>>
>>>>
>>>
>>> --
>>> Best regards,
>>> Igor Stasenko.
>>>
>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko.
>>
>
>
April 5, 2016
Re: [Pharo-dev] [ bloc ] I do not understand why some behavior is not in the right place
by Cyril Ferlicot Delbecque
On 05/04/2016 15:08, Igor Stasenko wrote:
>
>
> On 5 April 2016 at 15:58, phil(a)highoctane.be <mailto:phil@highoctane.be>
> <phil(a)highoctane.be <mailto:phil@highoctane.be>> wrote:
>
> Made a quick gist of of
> this: https://gist.github.com/philippeback/ef4d128e953de226cf40639641f83e04
>
> Thanks. Would be nice if someone with better English than mine skim
> trough it and fix bad language :)
This should be added in the meta data of Athens's configuration I think.
It would help people to find it.
>
> --
> Best regards,
> Igor Stasenko.
--
Cyril Ferlicot
http://www.synectique.eu
165 Avenue Bretagne
Lille 59000 France
April 5, 2016
Re: [Pharo-dev] [ bloc ] I do not understand why some behavior is not in the right place
by Aliaksei Syrel
Hello Igor
Thanks for extensive design explanation and effort!
Issues you mentioned in previous emails are important and need to be
addressed :)
fill(), stroke() fillPreserve() strokePreserve() need to disappear in the
end. We will come back to them later.
Let me tell a few words about Sparta.
Sparta implements Athens interface api (excluding some experimental stuff
to test possible performance boost in a few places) and does not have task
to remove Athens style and abstractions. Ideally Sparta will be AthensCairo
for bloc. I'm looking forward for your help :)
Here are some aspects in AthensCairo that Sparta tries to address in first
place:
- *Clipping in local coordinates*. It is critical in Bloc. You
implemented AthensCairo to have vector based rendering in Morphic and Pharo
in general. Morphic lives in global coordinates, so your choice to clip in
global coordinate is perfect! At the same time global clipping in bloc adds
complexity. Sparta clips always in local coordinates (user space in cairo
terminology).
- *Clip by arbitrary path*. Athens and AthenCairo expect to see
aRectangle as clipping region - your wise choice for morphic. In bloc I
would have clipping by arbitrary path. clipBy:during: gets aPath.
Rectangle/Color is polymorphic with path/paint in Sparta
- *Support of groups*. (maybe user-level aspect? like shadows) Groups
are powerful in cairo (do they exist outside of cairo?) and allow to draw
both transparent fill and stroke without overlapping using only one path.
On class side of BlElement there are examples (exampleCircle) that show
such behavior.
- *Do not maintain and set pathTransformation before each
render-dependent action.* Questionable but what if Canvas will not
maintain current state of pathTransform? Instead all transformations can be
directly applied on cairo_t using native calls. If there is a need to get
actual matrix we can ask cairo directly. From my perspective it simplifies
transformation stuff a little bit.
- *Benefit from cairo_save and cairo_restore.* AthensCairo maintains
state manually by setting transformation matrix and clip. Instead we could
save and restore state without caring about clip/matrix which simplifies
code. Check SpartaCanvas>>#clipBy:during:
Cheers,
Alex
On Tue, Apr 5, 2016 at 2:12 PM, Igor Stasenko <siguctua(a)gmail.com> wrote:
>
> Couple more words about that fill() function abstraction.
> Now you probably understand why there's no notion of stroke operation in
> Athens.
> Because instead of introducing it that way, by adding new kind of a
> function
> stroke(shape,paint)
> from our perspective, it falls into our more generic fill() function,
> except that
> instead of literally filling the shape we deciding to paint a stroke:
> fill(shape, strokePaint).
>
> As i said, there's nothing that tells that fill() function must affect
> only areas enclosed by the shape.
> For instance, you could imagine, that i'm in contrary, may want to fill
> everything , but the area(s) enclosed by given shape. And that still can be
> represented as invocation of our generic fill() function, except that we
> will use a different kind of paint, that will fill everything outside
> designated region, i.e.:
> fill(shape, fillOutsidePaint)
>
>
>
> On 5 April 2016 at 14:33, Igor Stasenko <siguctua(a)gmail.com> wrote:
>
>>
>>
>> On 5 April 2016 at 04:00, Ben Coman <btc(a)openinworld.com> wrote:
>>
>>> On Tue, Apr 5, 2016 at 2:51 AM, Igor Stasenko <siguctua(a)gmail.com>
>>> wrote:
>>> >
>>> > Some more bashing today.. (don't take it personal, i may be wrong)
>>> >
>>> > BlPath hierarchy.. and BlShape.
>>> >
>>> > Why you redefining what is shape and what is path?
>>> > Of course, you are free to do it in Bloc..
>>> > But in terms of Athens, all of BlPath are actually - shapes..
>>> > And BlShape is some kind of encapsulation of shape, paints and
>>> transform.
>>> > It is a dumb state holder without any extra logic.
>>> >
>>> > My rule of thumb: do not produce dumb state holders. They has to be
>>> smart,
>>> > else it makes no sense in creating separate entity and designating it
>>> as
>>> > something else than any other bunch of data thrown into single clump,
>>> > sitting there deaf, blind, dead and silent until someone else will
>>> grab it
>>> > somewhere
>>> > and start using it for own purpose.
>>> >
>>> > Sure, i could understand, why you potentially may want such object(s)
>>> > around,
>>> > but it is not shape anymore and i wouldn't call it like that. Because
>>> shape
>>> > are shape, and has nothing to do with paints and transform,
>>> > it don't knows and don't cares whether it will be filled or stroked or
>>> both,
>>> > and how many times, and if there will be single paint or thousand.
>>> > Such kind of properties is simply orthogonal to what shape existing
>>> for,
>>> > because it exists only to define geometry.
>>> >
>>> > I think all of that came from not understanding the roles of objects
>>> and how
>>> > they interact in Athens.
>>>
>>> Can you point us to documentation that describes Athen's architecture
>>> for these interactions?
>>> (sorry I haven't checked class comments, but I'm looking to start with
>>> something at higher level anyway)
>>>
>>
>> No, i can't point it out. And you are right , this is nobody else's fault
>> than my own. I feel ashamed. Sure how i could demand that people understand
>> the concepts, if i didn't explained then anywhere (or if i did, it is not
>> in easily reachable place).
>>
>> So, lets fix that. I will write it down here, and you can pick it up and
>> find suitable place for it.
>>
>> ----------
>> Basic abstractions behind Athens.
>>
>> Since Athens is about drawing graphics, we need a media where all drawing
>> operations will appear. We call that media a surface.
>> The surface is abstract. It can have set dimensions, or don't. We don't
>> define if it representing some kind of physical surface (like part of the
>> display screen), or how it storing the data inside. We leaving an
>> introduction of such details to concrete surface implementation.
>> All that matters is that surface is a final target of all our drawing
>> operations.
>> Therefore, in Athens, a surface is usually a starting point where all
>> begins from, and you doing so by creating a specific surface.
>> It is surface's responsibility then, to provide user a means how he can
>> draw on it, and therefore there is a number of factory methods, that
>> allowing you to create a canvas, paints and shapes. All those three are
>> specific implementation of AthensCanvas, AthensPaint and AthensShape
>> protocols, suitable to be used with specific surface implementation that
>> you using.
>>
>> Canvas.
>> Canvas represents a basic drawing context. We don't allow a direct
>> operations with surface, but instead we provide a context, that contains
>> and carries all information that represents a current stage of drawing
>> operations.
>> This includes things like, current coordinate transformation(s),
>> currently selected paint and shape, and paint mode.
>>
>> In order to obtain canvas, one must use #drawDuring: message sent to
>> surface with block as argument. The given block receives an instance of
>> AthensCanvas as a single parameter. We intentionally enclosing all possible
>> drawing operations within a block to make sure that when we leave, we can
>> safely release all resources that was allocated, required to hold the
>> drawing context state. By exposing it in such form, we also making sure
>> that nothing can alter the surface outside a given block. That way, it
>> gives users a definitive answer, whether he finished drawing operations or
>> not, and if it safe to operate with surface for things like saving it to
>> file, or using it as a source for more complex operations, like acting as a
>> paint to fill area(s) inside another surface etc.
>>
>> Paints and shapes.
>> A starting point is answering a question, how we can represent a
>> simplest, elementary drawing operation on a surface without putting too
>> much constraints.
>> We doing so by postulating that any elementary drawing operation can be
>> expressed by a function:
>>
>> fill(paint, shape)
>>
>> Please, note that 'fill' here is not a literally fill given shape with
>> given paint. We call it 'fill' for simplicity reason. It can anything that
>> altering the surface, but always taking into account given parameters:
>> paint and shape.
>>
>> Then, from that perspective we can clearly say what are the roles and
>> responsibility of shapes and paints.
>>
>> The shape defines the affected region, its geometry and location,
>> while paint defines how that region will be altered.
>> In this way, most of more complex operations can be expressed as a series
>> of such function invocations by using various paints and shapes.
>>
>> Such representation also gives us a minimal set of roles, a building
>> bricks, that we need to introduce in order to represent any kind of drawing
>> operation we may need, as well as a minimal functionality in order to
>> implement such function(s). And therefore a minimal protocol(s), that all
>> paints and shapes should implement.
>>
>> Since there potentially infinite number of various paint kinds and shape
>> kinds, we cannot make a single function that will implement all possible
>> permutations in order to fill shape with concrete paint.
>> To solve that we introducing a straight dispatch mechanism, where we
>> delegate the responsibility of implementing a concrete case, first to
>> shape, and then to paint.
>>
>> The API representing this function in canvas by #draw protocol.
>> It takes currently selected paint and currently selected shape and
>> starting dispatch:
>>
>> draw
>> "Fill the currently selected shape with currently selected paint"
>> ^ shape paintFillsUsing: paint on: self
>>
>> So, first it goes to the shape, by sending #paintFillsUsing:on: ,
>> then shape dispatching it further to paint by sending appropriate message
>> (be it #athensFillPath:on: or #athensFillRectangle:on: or anything else,
>> if you want to introduce new kind of shape representation and implement it
>> accordingly).
>> Such dispatch gives us an ability to easily extend the framework by
>> introducing new kind of shapes and paints , by implementing new kind of
>> fill() functions for them.
>>
>> -----------
>>
>> I hope that will make clear at least part of things what is there, behind
>> the scenes.
>>
>>
>>> cheers -ben
>>>
>>>
>>
>> --
>> Best regards,
>> Igor Stasenko.
>>
>
>
>
> --
> Best regards,
> Igor Stasenko.
>
April 5, 2016
Re: [Pharo-dev] [ bloc ] I do not understand why some behavior is not in the right place
by Igor Stasenko
On 5 April 2016 at 15:58, phil(a)highoctane.be <phil(a)highoctane.be> wrote:
> Made a quick gist of of this:
> https://gist.github.com/philippeback/ef4d128e953de226cf40639641f83e04
>
> Thanks. Would be nice if someone with better English than mine skim trough
it and fix bad language :)
> On Tue, Apr 5, 2016 at 1:33 PM, Igor Stasenko <siguctua(a)gmail.com> wrote:
>
>>
>>
>> On 5 April 2016 at 04:00, Ben Coman <btc(a)openinworld.com> wrote:
>>
>>> On Tue, Apr 5, 2016 at 2:51 AM, Igor Stasenko <siguctua(a)gmail.com>
>>> wrote:
>>> >
>>> > Some more bashing today.. (don't take it personal, i may be wrong)
>>> >
>>> > BlPath hierarchy.. and BlShape.
>>> >
>>> > Why you redefining what is shape and what is path?
>>> > Of course, you are free to do it in Bloc..
>>> > But in terms of Athens, all of BlPath are actually - shapes..
>>> > And BlShape is some kind of encapsulation of shape, paints and
>>> transform.
>>> > It is a dumb state holder without any extra logic.
>>> >
>>> > My rule of thumb: do not produce dumb state holders. They has to be
>>> smart,
>>> > else it makes no sense in creating separate entity and designating it
>>> as
>>> > something else than any other bunch of data thrown into single clump,
>>> > sitting there deaf, blind, dead and silent until someone else will
>>> grab it
>>> > somewhere
>>> > and start using it for own purpose.
>>> >
>>> > Sure, i could understand, why you potentially may want such object(s)
>>> > around,
>>> > but it is not shape anymore and i wouldn't call it like that. Because
>>> shape
>>> > are shape, and has nothing to do with paints and transform,
>>> > it don't knows and don't cares whether it will be filled or stroked or
>>> both,
>>> > and how many times, and if there will be single paint or thousand.
>>> > Such kind of properties is simply orthogonal to what shape existing
>>> for,
>>> > because it exists only to define geometry.
>>> >
>>> > I think all of that came from not understanding the roles of objects
>>> and how
>>> > they interact in Athens.
>>>
>>> Can you point us to documentation that describes Athen's architecture
>>> for these interactions?
>>> (sorry I haven't checked class comments, but I'm looking to start with
>>> something at higher level anyway)
>>>
>>
>> No, i can't point it out. And you are right , this is nobody else's fault
>> than my own. I feel ashamed. Sure how i could demand that people understand
>> the concepts, if i didn't explained then anywhere (or if i did, it is not
>> in easily reachable place).
>>
>> So, lets fix that. I will write it down here, and you can pick it up and
>> find suitable place for it.
>>
>> ----------
>> Basic abstractions behind Athens.
>>
>> Since Athens is about drawing graphics, we need a media where all drawing
>> operations will appear. We call that media a surface.
>> The surface is abstract. It can have set dimensions, or don't. We don't
>> define if it representing some kind of physical surface (like part of the
>> display screen), or how it storing the data inside. We leaving an
>> introduction of such details to concrete surface implementation.
>> All that matters is that surface is a final target of all our drawing
>> operations.
>> Therefore, in Athens, a surface is usually a starting point where all
>> begins from, and you doing so by creating a specific surface.
>> It is surface's responsibility then, to provide user a means how he can
>> draw on it, and therefore there is a number of factory methods, that
>> allowing you to create a canvas, paints and shapes. All those three are
>> specific implementation of AthensCanvas, AthensPaint and AthensShape
>> protocols, suitable to be used with specific surface implementation that
>> you using.
>>
>> Canvas.
>> Canvas represents a basic drawing context. We don't allow a direct
>> operations with surface, but instead we provide a context, that contains
>> and carries all information that represents a current stage of drawing
>> operations.
>> This includes things like, current coordinate transformation(s),
>> currently selected paint and shape, and paint mode.
>>
>> In order to obtain canvas, one must use #drawDuring: message sent to
>> surface with block as argument. The given block receives an instance of
>> AthensCanvas as a single parameter. We intentionally enclosing all possible
>> drawing operations within a block to make sure that when we leave, we can
>> safely release all resources that was allocated, required to hold the
>> drawing context state. By exposing it in such form, we also making sure
>> that nothing can alter the surface outside a given block. That way, it
>> gives users a definitive answer, whether he finished drawing operations or
>> not, and if it safe to operate with surface for things like saving it to
>> file, or using it as a source for more complex operations, like acting as a
>> paint to fill area(s) inside another surface etc.
>>
>> Paints and shapes.
>> A starting point is answering a question, how we can represent a
>> simplest, elementary drawing operation on a surface without putting too
>> much constraints.
>> We doing so by postulating that any elementary drawing operation can be
>> expressed by a function:
>>
>> fill(paint, shape)
>>
>> Please, note that 'fill' here is not a literally fill given shape with
>> given paint. We call it 'fill' for simplicity reason. It can anything that
>> altering the surface, but always taking into account given parameters:
>> paint and shape.
>>
>> Then, from that perspective we can clearly say what are the roles and
>> responsibility of shapes and paints.
>>
>> The shape defines the affected region, its geometry and location,
>> while paint defines how that region will be altered.
>> In this way, most of more complex operations can be expressed as a series
>> of such function invocations by using various paints and shapes.
>>
>> Such representation also gives us a minimal set of roles, a building
>> bricks, that we need to introduce in order to represent any kind of drawing
>> operation we may need, as well as a minimal functionality in order to
>> implement such function(s). And therefore a minimal protocol(s), that all
>> paints and shapes should implement.
>>
>> Since there potentially infinite number of various paint kinds and shape
>> kinds, we cannot make a single function that will implement all possible
>> permutations in order to fill shape with concrete paint.
>> To solve that we introducing a straight dispatch mechanism, where we
>> delegate the responsibility of implementing a concrete case, first to
>> shape, and then to paint.
>>
>> The API representing this function in canvas by #draw protocol.
>> It takes currently selected paint and currently selected shape and
>> starting dispatch:
>>
>> draw
>> "Fill the currently selected shape with currently selected paint"
>> ^ shape paintFillsUsing: paint on: self
>>
>> So, first it goes to the shape, by sending #paintFillsUsing:on: ,
>> then shape dispatching it further to paint by sending appropriate message
>> (be it #athensFillPath:on: or #athensFillRectangle:on: or anything else,
>> if you want to introduce new kind of shape representation and implement it
>> accordingly).
>> Such dispatch gives us an ability to easily extend the framework by
>> introducing new kind of shapes and paints , by implementing new kind of
>> fill() functions for them.
>>
>> -----------
>>
>> I hope that will make clear at least part of things what is there, behind
>> the scenes.
>>
>>
>>> cheers -ben
>>>
>>>
>>
>> --
>> Best regards,
>> Igor Stasenko.
>>
>
>
--
Best regards,
Igor Stasenko.
April 5, 2016
Re: [Pharo-dev] [ bloc ] I do not understand why some behavior is not in the right place
by phil@highoctane.be
Made a quick gist of of this:
https://gist.github.com/philippeback/ef4d128e953de226cf40639641f83e04
On Tue, Apr 5, 2016 at 1:33 PM, Igor Stasenko <siguctua(a)gmail.com> wrote:
>
>
> On 5 April 2016 at 04:00, Ben Coman <btc(a)openinworld.com> wrote:
>
>> On Tue, Apr 5, 2016 at 2:51 AM, Igor Stasenko <siguctua(a)gmail.com> wrote:
>> >
>> > Some more bashing today.. (don't take it personal, i may be wrong)
>> >
>> > BlPath hierarchy.. and BlShape.
>> >
>> > Why you redefining what is shape and what is path?
>> > Of course, you are free to do it in Bloc..
>> > But in terms of Athens, all of BlPath are actually - shapes..
>> > And BlShape is some kind of encapsulation of shape, paints and
>> transform.
>> > It is a dumb state holder without any extra logic.
>> >
>> > My rule of thumb: do not produce dumb state holders. They has to be
>> smart,
>> > else it makes no sense in creating separate entity and designating it as
>> > something else than any other bunch of data thrown into single clump,
>> > sitting there deaf, blind, dead and silent until someone else will grab
>> it
>> > somewhere
>> > and start using it for own purpose.
>> >
>> > Sure, i could understand, why you potentially may want such object(s)
>> > around,
>> > but it is not shape anymore and i wouldn't call it like that. Because
>> shape
>> > are shape, and has nothing to do with paints and transform,
>> > it don't knows and don't cares whether it will be filled or stroked or
>> both,
>> > and how many times, and if there will be single paint or thousand.
>> > Such kind of properties is simply orthogonal to what shape existing for,
>> > because it exists only to define geometry.
>> >
>> > I think all of that came from not understanding the roles of objects
>> and how
>> > they interact in Athens.
>>
>> Can you point us to documentation that describes Athen's architecture
>> for these interactions?
>> (sorry I haven't checked class comments, but I'm looking to start with
>> something at higher level anyway)
>>
>
> No, i can't point it out. And you are right , this is nobody else's fault
> than my own. I feel ashamed. Sure how i could demand that people understand
> the concepts, if i didn't explained then anywhere (or if i did, it is not
> in easily reachable place).
>
> So, lets fix that. I will write it down here, and you can pick it up and
> find suitable place for it.
>
> ----------
> Basic abstractions behind Athens.
>
> Since Athens is about drawing graphics, we need a media where all drawing
> operations will appear. We call that media a surface.
> The surface is abstract. It can have set dimensions, or don't. We don't
> define if it representing some kind of physical surface (like part of the
> display screen), or how it storing the data inside. We leaving an
> introduction of such details to concrete surface implementation.
> All that matters is that surface is a final target of all our drawing
> operations.
> Therefore, in Athens, a surface is usually a starting point where all
> begins from, and you doing so by creating a specific surface.
> It is surface's responsibility then, to provide user a means how he can
> draw on it, and therefore there is a number of factory methods, that
> allowing you to create a canvas, paints and shapes. All those three are
> specific implementation of AthensCanvas, AthensPaint and AthensShape
> protocols, suitable to be used with specific surface implementation that
> you using.
>
> Canvas.
> Canvas represents a basic drawing context. We don't allow a direct
> operations with surface, but instead we provide a context, that contains
> and carries all information that represents a current stage of drawing
> operations.
> This includes things like, current coordinate transformation(s), currently
> selected paint and shape, and paint mode.
>
> In order to obtain canvas, one must use #drawDuring: message sent to
> surface with block as argument. The given block receives an instance of
> AthensCanvas as a single parameter. We intentionally enclosing all possible
> drawing operations within a block to make sure that when we leave, we can
> safely release all resources that was allocated, required to hold the
> drawing context state. By exposing it in such form, we also making sure
> that nothing can alter the surface outside a given block. That way, it
> gives users a definitive answer, whether he finished drawing operations or
> not, and if it safe to operate with surface for things like saving it to
> file, or using it as a source for more complex operations, like acting as a
> paint to fill area(s) inside another surface etc.
>
> Paints and shapes.
> A starting point is answering a question, how we can represent a simplest,
> elementary drawing operation on a surface without putting too much
> constraints.
> We doing so by postulating that any elementary drawing operation can be
> expressed by a function:
>
> fill(paint, shape)
>
> Please, note that 'fill' here is not a literally fill given shape with
> given paint. We call it 'fill' for simplicity reason. It can anything that
> altering the surface, but always taking into account given parameters:
> paint and shape.
>
> Then, from that perspective we can clearly say what are the roles and
> responsibility of shapes and paints.
>
> The shape defines the affected region, its geometry and location,
> while paint defines how that region will be altered.
> In this way, most of more complex operations can be expressed as a series
> of such function invocations by using various paints and shapes.
>
> Such representation also gives us a minimal set of roles, a building
> bricks, that we need to introduce in order to represent any kind of drawing
> operation we may need, as well as a minimal functionality in order to
> implement such function(s). And therefore a minimal protocol(s), that all
> paints and shapes should implement.
>
> Since there potentially infinite number of various paint kinds and shape
> kinds, we cannot make a single function that will implement all possible
> permutations in order to fill shape with concrete paint.
> To solve that we introducing a straight dispatch mechanism, where we
> delegate the responsibility of implementing a concrete case, first to
> shape, and then to paint.
>
> The API representing this function in canvas by #draw protocol.
> It takes currently selected paint and currently selected shape and
> starting dispatch:
>
> draw
> "Fill the currently selected shape with currently selected paint"
> ^ shape paintFillsUsing: paint on: self
>
> So, first it goes to the shape, by sending #paintFillsUsing:on: ,
> then shape dispatching it further to paint by sending appropriate message
> (be it #athensFillPath:on: or #athensFillRectangle:on: or anything else,
> if you want to introduce new kind of shape representation and implement it
> accordingly).
> Such dispatch gives us an ability to easily extend the framework by
> introducing new kind of shapes and paints , by implementing new kind of
> fill() functions for them.
>
> -----------
>
> I hope that will make clear at least part of things what is there, behind
> the scenes.
>
>
>> cheers -ben
>>
>>
>
> --
> Best regards,
> Igor Stasenko.
>
April 5, 2016
Re: [Pharo-dev] TxText model
by Igor Stasenko
On 5 April 2016 at 04:16, Ben Coman <btc(a)openinworld.com> wrote:
> On Mon, Apr 4, 2016 at 9:49 PM, Igor Stasenko <siguctua(a)gmail.com> wrote:
> >
> >
> > On 4 April 2016 at 16:32, Thierry Goubier <thierry.goubier(a)gmail.com>
> wrote:
> >>
> >>
> >>
> >> 2016-04-04 15:23 GMT+02:00 Igor Stasenko <siguctua(a)gmail.com>:
> >>>
> >>>
> >>>>
> >>> Analogies don't work. Right :) I never used Pillar and have remote
> ideas
> >>> about what it does or requires. From that perspective you appeal to
> wrong
> >>> person. On your place i would be asking a guy who knows Pillar innards
> about
> >>> it.
>
> Please see...
>
> [1]
> http://esug.org/data/ESUG2015/4%20thursday/1600-1630%20Pilar/Pillar.pdf
>
> Okay. Now i remember.
Yeah, i can easily imagine making a transformer that renders a pillar
markup text into TxText instance, by implementing an yet another exporter,
like PRTxTextWriter.
Certain features would be impossible right now, but for simple docs i guess
it may work just fine.
> [2]
> https://ci.inria.fr/pharo-contribution/job/EnterprisePharoBook/lastSuccessf…
>
> Most (all?) of docs at [3] are done using Pillar...
> [3] https://github.com/SquareBracketAssociates
>
> cheers -ben
>
>
--
Best regards,
Igor Stasenko.
April 5, 2016
Re: [Pharo-dev] [ bloc ] I do not understand why some behavior is not in the right place
by Igor Stasenko
Couple more words about that fill() function abstraction.
Now you probably understand why there's no notion of stroke operation in
Athens.
Because instead of introducing it that way, by adding new kind of a function
stroke(shape,paint)
from our perspective, it falls into our more generic fill() function,
except that
instead of literally filling the shape we deciding to paint a stroke:
fill(shape, strokePaint).
As i said, there's nothing that tells that fill() function must affect only
areas enclosed by the shape.
For instance, you could imagine, that i'm in contrary, may want to fill
everything , but the area(s) enclosed by given shape. And that still can be
represented as invocation of our generic fill() function, except that we
will use a different kind of paint, that will fill everything outside
designated region, i.e.:
fill(shape, fillOutsidePaint)
On 5 April 2016 at 14:33, Igor Stasenko <siguctua(a)gmail.com> wrote:
>
>
> On 5 April 2016 at 04:00, Ben Coman <btc(a)openinworld.com> wrote:
>
>> On Tue, Apr 5, 2016 at 2:51 AM, Igor Stasenko <siguctua(a)gmail.com> wrote:
>> >
>> > Some more bashing today.. (don't take it personal, i may be wrong)
>> >
>> > BlPath hierarchy.. and BlShape.
>> >
>> > Why you redefining what is shape and what is path?
>> > Of course, you are free to do it in Bloc..
>> > But in terms of Athens, all of BlPath are actually - shapes..
>> > And BlShape is some kind of encapsulation of shape, paints and
>> transform.
>> > It is a dumb state holder without any extra logic.
>> >
>> > My rule of thumb: do not produce dumb state holders. They has to be
>> smart,
>> > else it makes no sense in creating separate entity and designating it as
>> > something else than any other bunch of data thrown into single clump,
>> > sitting there deaf, blind, dead and silent until someone else will grab
>> it
>> > somewhere
>> > and start using it for own purpose.
>> >
>> > Sure, i could understand, why you potentially may want such object(s)
>> > around,
>> > but it is not shape anymore and i wouldn't call it like that. Because
>> shape
>> > are shape, and has nothing to do with paints and transform,
>> > it don't knows and don't cares whether it will be filled or stroked or
>> both,
>> > and how many times, and if there will be single paint or thousand.
>> > Such kind of properties is simply orthogonal to what shape existing for,
>> > because it exists only to define geometry.
>> >
>> > I think all of that came from not understanding the roles of objects
>> and how
>> > they interact in Athens.
>>
>> Can you point us to documentation that describes Athen's architecture
>> for these interactions?
>> (sorry I haven't checked class comments, but I'm looking to start with
>> something at higher level anyway)
>>
>
> No, i can't point it out. And you are right , this is nobody else's fault
> than my own. I feel ashamed. Sure how i could demand that people understand
> the concepts, if i didn't explained then anywhere (or if i did, it is not
> in easily reachable place).
>
> So, lets fix that. I will write it down here, and you can pick it up and
> find suitable place for it.
>
> ----------
> Basic abstractions behind Athens.
>
> Since Athens is about drawing graphics, we need a media where all drawing
> operations will appear. We call that media a surface.
> The surface is abstract. It can have set dimensions, or don't. We don't
> define if it representing some kind of physical surface (like part of the
> display screen), or how it storing the data inside. We leaving an
> introduction of such details to concrete surface implementation.
> All that matters is that surface is a final target of all our drawing
> operations.
> Therefore, in Athens, a surface is usually a starting point where all
> begins from, and you doing so by creating a specific surface.
> It is surface's responsibility then, to provide user a means how he can
> draw on it, and therefore there is a number of factory methods, that
> allowing you to create a canvas, paints and shapes. All those three are
> specific implementation of AthensCanvas, AthensPaint and AthensShape
> protocols, suitable to be used with specific surface implementation that
> you using.
>
> Canvas.
> Canvas represents a basic drawing context. We don't allow a direct
> operations with surface, but instead we provide a context, that contains
> and carries all information that represents a current stage of drawing
> operations.
> This includes things like, current coordinate transformation(s), currently
> selected paint and shape, and paint mode.
>
> In order to obtain canvas, one must use #drawDuring: message sent to
> surface with block as argument. The given block receives an instance of
> AthensCanvas as a single parameter. We intentionally enclosing all possible
> drawing operations within a block to make sure that when we leave, we can
> safely release all resources that was allocated, required to hold the
> drawing context state. By exposing it in such form, we also making sure
> that nothing can alter the surface outside a given block. That way, it
> gives users a definitive answer, whether he finished drawing operations or
> not, and if it safe to operate with surface for things like saving it to
> file, or using it as a source for more complex operations, like acting as a
> paint to fill area(s) inside another surface etc.
>
> Paints and shapes.
> A starting point is answering a question, how we can represent a simplest,
> elementary drawing operation on a surface without putting too much
> constraints.
> We doing so by postulating that any elementary drawing operation can be
> expressed by a function:
>
> fill(paint, shape)
>
> Please, note that 'fill' here is not a literally fill given shape with
> given paint. We call it 'fill' for simplicity reason. It can anything that
> altering the surface, but always taking into account given parameters:
> paint and shape.
>
> Then, from that perspective we can clearly say what are the roles and
> responsibility of shapes and paints.
>
> The shape defines the affected region, its geometry and location,
> while paint defines how that region will be altered.
> In this way, most of more complex operations can be expressed as a series
> of such function invocations by using various paints and shapes.
>
> Such representation also gives us a minimal set of roles, a building
> bricks, that we need to introduce in order to represent any kind of drawing
> operation we may need, as well as a minimal functionality in order to
> implement such function(s). And therefore a minimal protocol(s), that all
> paints and shapes should implement.
>
> Since there potentially infinite number of various paint kinds and shape
> kinds, we cannot make a single function that will implement all possible
> permutations in order to fill shape with concrete paint.
> To solve that we introducing a straight dispatch mechanism, where we
> delegate the responsibility of implementing a concrete case, first to
> shape, and then to paint.
>
> The API representing this function in canvas by #draw protocol.
> It takes currently selected paint and currently selected shape and
> starting dispatch:
>
> draw
> "Fill the currently selected shape with currently selected paint"
> ^ shape paintFillsUsing: paint on: self
>
> So, first it goes to the shape, by sending #paintFillsUsing:on: ,
> then shape dispatching it further to paint by sending appropriate message
> (be it #athensFillPath:on: or #athensFillRectangle:on: or anything else,
> if you want to introduce new kind of shape representation and implement it
> accordingly).
> Such dispatch gives us an ability to easily extend the framework by
> introducing new kind of shapes and paints , by implementing new kind of
> fill() functions for them.
>
> -----------
>
> I hope that will make clear at least part of things what is there, behind
> the scenes.
>
>
>> cheers -ben
>>
>>
>
> --
> Best regards,
> Igor Stasenko.
>
--
Best regards,
Igor Stasenko.
April 5, 2016
Re: [Pharo-dev] [ bloc ] I do not understand why some behavior is not in the right place
by Igor Stasenko
On 5 April 2016 at 04:00, Ben Coman <btc(a)openinworld.com> wrote:
> On Tue, Apr 5, 2016 at 2:51 AM, Igor Stasenko <siguctua(a)gmail.com> wrote:
> >
> > Some more bashing today.. (don't take it personal, i may be wrong)
> >
> > BlPath hierarchy.. and BlShape.
> >
> > Why you redefining what is shape and what is path?
> > Of course, you are free to do it in Bloc..
> > But in terms of Athens, all of BlPath are actually - shapes..
> > And BlShape is some kind of encapsulation of shape, paints and transform.
> > It is a dumb state holder without any extra logic.
> >
> > My rule of thumb: do not produce dumb state holders. They has to be
> smart,
> > else it makes no sense in creating separate entity and designating it as
> > something else than any other bunch of data thrown into single clump,
> > sitting there deaf, blind, dead and silent until someone else will grab
> it
> > somewhere
> > and start using it for own purpose.
> >
> > Sure, i could understand, why you potentially may want such object(s)
> > around,
> > but it is not shape anymore and i wouldn't call it like that. Because
> shape
> > are shape, and has nothing to do with paints and transform,
> > it don't knows and don't cares whether it will be filled or stroked or
> both,
> > and how many times, and if there will be single paint or thousand.
> > Such kind of properties is simply orthogonal to what shape existing for,
> > because it exists only to define geometry.
> >
> > I think all of that came from not understanding the roles of objects and
> how
> > they interact in Athens.
>
> Can you point us to documentation that describes Athen's architecture
> for these interactions?
> (sorry I haven't checked class comments, but I'm looking to start with
> something at higher level anyway)
>
No, i can't point it out. And you are right , this is nobody else's fault
than my own. I feel ashamed. Sure how i could demand that people understand
the concepts, if i didn't explained then anywhere (or if i did, it is not
in easily reachable place).
So, lets fix that. I will write it down here, and you can pick it up and
find suitable place for it.
----------
Basic abstractions behind Athens.
Since Athens is about drawing graphics, we need a media where all drawing
operations will appear. We call that media a surface.
The surface is abstract. It can have set dimensions, or don't. We don't
define if it representing some kind of physical surface (like part of the
display screen), or how it storing the data inside. We leaving an
introduction of such details to concrete surface implementation.
All that matters is that surface is a final target of all our drawing
operations.
Therefore, in Athens, a surface is usually a starting point where all
begins from, and you doing so by creating a specific surface.
It is surface's responsibility then, to provide user a means how he can
draw on it, and therefore there is a number of factory methods, that
allowing you to create a canvas, paints and shapes. All those three are
specific implementation of AthensCanvas, AthensPaint and AthensShape
protocols, suitable to be used with specific surface implementation that
you using.
Canvas.
Canvas represents a basic drawing context. We don't allow a direct
operations with surface, but instead we provide a context, that contains
and carries all information that represents a current stage of drawing
operations.
This includes things like, current coordinate transformation(s), currently
selected paint and shape, and paint mode.
In order to obtain canvas, one must use #drawDuring: message sent to
surface with block as argument. The given block receives an instance of
AthensCanvas as a single parameter. We intentionally enclosing all possible
drawing operations within a block to make sure that when we leave, we can
safely release all resources that was allocated, required to hold the
drawing context state. By exposing it in such form, we also making sure
that nothing can alter the surface outside a given block. That way, it
gives users a definitive answer, whether he finished drawing operations or
not, and if it safe to operate with surface for things like saving it to
file, or using it as a source for more complex operations, like acting as a
paint to fill area(s) inside another surface etc.
Paints and shapes.
A starting point is answering a question, how we can represent a simplest,
elementary drawing operation on a surface without putting too much
constraints.
We doing so by postulating that any elementary drawing operation can be
expressed by a function:
fill(paint, shape)
Please, note that 'fill' here is not a literally fill given shape with
given paint. We call it 'fill' for simplicity reason. It can anything that
altering the surface, but always taking into account given parameters:
paint and shape.
Then, from that perspective we can clearly say what are the roles and
responsibility of shapes and paints.
The shape defines the affected region, its geometry and location,
while paint defines how that region will be altered.
In this way, most of more complex operations can be expressed as a series
of such function invocations by using various paints and shapes.
Such representation also gives us a minimal set of roles, a building
bricks, that we need to introduce in order to represent any kind of drawing
operation we may need, as well as a minimal functionality in order to
implement such function(s). And therefore a minimal protocol(s), that all
paints and shapes should implement.
Since there potentially infinite number of various paint kinds and shape
kinds, we cannot make a single function that will implement all possible
permutations in order to fill shape with concrete paint.
To solve that we introducing a straight dispatch mechanism, where we
delegate the responsibility of implementing a concrete case, first to
shape, and then to paint.
The API representing this function in canvas by #draw protocol.
It takes currently selected paint and currently selected shape and starting
dispatch:
draw
"Fill the currently selected shape with currently selected paint"
^ shape paintFillsUsing: paint on: self
So, first it goes to the shape, by sending #paintFillsUsing:on: ,
then shape dispatching it further to paint by sending appropriate message
(be it #athensFillPath:on: or #athensFillRectangle:on: or anything else, if
you want to introduce new kind of shape representation and implement it
accordingly).
Such dispatch gives us an ability to easily extend the framework by
introducing new kind of shapes and paints , by implementing new kind of
fill() functions for them.
-----------
I hope that will make clear at least part of things what is there, behind
the scenes.
> cheers -ben
>
>
--
Best regards,
Igor Stasenko.
April 5, 2016