Hello
NullEncoder is subclass of object ([1] for full hierachy). It is a superclass of Canvas.
What is the function of NullEncoder. No class comment so far?
Regards Hannes
-------------------------------------------------------------------------------------------------------------------------------
[1] NullEncoder printHierarchy ' ProtoObject #() Object #() NullEncoder #(''target'' ''filterSelector'') FlattenEncoder #() ByteEncoder #() PrintableEncoder #() PostscriptEncoder #() PostscriptEncoderToDisk #() PropertyListEncoder #() Canvas #() ColorMappingCanvas #(''myCanvas'') AlphaBlendingCanvas #(''alpha'') ShadowDrawingCanvas #(''shadowColor'') FormCanvas #(''origin'' ''clipRect'' ''form'' ''port'' ''shadowColor'') BalloonCanvas #(''transform'' ''colorTransform'' ''engine'' ''aaLevel'' ''deferred'') BlueFormCanvas #() ColorPatchCanvas #(''stopMorph'' ''foundMorph'' ''doStop'') MultiResolutionCanvas #(''deferredMorphs'') PluggableCanvas #() BufferedCanvas #(''remote'' ''previousVersion'' ''lastTick'' ''dirtyRect'' ''mirrorOfScreen'') CachingCanvas #(''cacheCanvas'' ''mainCanvas'') ClippingCanvas #(''canvas'' ''clipRect'') MultiCanvas #(''canvases'' ''extent'' ''depth'') NullCanvas #() PostscriptCanvas #(''origin'' ''clipRect'' ''currentColor'' ''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack'' ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph'' ''initialScale'' ''savedMorphExtent'' ''currentTransformation'' ''printSpecs'' ''pages'') DSCPostscriptCanvas #() DSCPostscriptCanvasToDisk #() EPSCanvas #() RemoteCanvas #(''innerClipRect'' ''outerClipRect'' ''transform'' ''connection'' ''shadowColor'')'
P.S.
There is no NullEncoder in Pharo.
The class Canvas is not in a package 'Morphic-Support' but in a package 'Graphics-Canvas'.
There is no 'Graphics-Canvas' package in Squeak. [2]
Seems like a good idea to move Canvas and subclasses to a package 'Graphics-Canvas' as well.
[2] Graphics package in Squeak 6.0a-17405
Graphics-Display Objects Graphics-External-Ffenestri Graphics-Files Graphics-Fonts Graphics-Primitives Graphics-Text Graphics-Transformations GraphicsTests-Files GraphicsTests-Primitives GraphicsTests-Text
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
Hello
NullEncoder is subclass of object ([1] for full hierachy). It is a superclass of Canvas.
What is the function of NullEncoder. No class comment so far?
Regards Hannes
[1] NullEncoder printHierarchy ' ProtoObject #() Object #() NullEncoder #(''target'' ''filterSelector'') FlattenEncoder #() ByteEncoder #() PrintableEncoder #() PostscriptEncoder #() PostscriptEncoderToDisk #() PropertyListEncoder #() Canvas #() ColorMappingCanvas #(''myCanvas'') AlphaBlendingCanvas #(''alpha'') ShadowDrawingCanvas #(''shadowColor'') FormCanvas #(''origin'' ''clipRect'' ''form'' ''port'' ''shadowColor'') BalloonCanvas #(''transform'' ''colorTransform'' ''engine'' ''aaLevel'' ''deferred'') BlueFormCanvas #() ColorPatchCanvas #(''stopMorph'' ''foundMorph'' ''doStop'') MultiResolutionCanvas #(''deferredMorphs'') PluggableCanvas #() BufferedCanvas #(''remote'' ''previousVersion'' ''lastTick'' ''dirtyRect'' ''mirrorOfScreen'') CachingCanvas #(''cacheCanvas'' ''mainCanvas'') ClippingCanvas #(''canvas'' ''clipRect'') MultiCanvas #(''canvases'' ''extent'' ''depth'') NullCanvas #() PostscriptCanvas #(''origin'' ''clipRect'' ''currentColor'' ''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack'' ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph'' ''initialScale'' ''savedMorphExtent'' ''currentTransformation'' ''printSpecs'' ''pages'') DSCPostscriptCanvas #() DSCPostscriptCanvasToDisk #() EPSCanvas #() RemoteCanvas #(''innerClipRect'' ''outerClipRect'' ''transform'' ''connection'' ''shadowColor'')'
We have
NullEncoder FlattenEncoder Canvas
there are no direct users of NullEncoder and FlattenEncoder.
FlattenEncoder class comment is just
'The simplest possible encoding: leave the objects as is.'
a bit terse. Does not really say what the issue is about.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
P.S.
There is no NullEncoder in Pharo.
The class Canvas is not in a package 'Morphic-Support' but in a package 'Graphics-Canvas'.
There is no 'Graphics-Canvas' package in Squeak. [2]
Seems like a good idea to move Canvas and subclasses to a package 'Graphics-Canvas' as well.
[2] Graphics package in Squeak 6.0a-17405
Graphics-Display Objects Graphics-External-Ffenestri Graphics-Files Graphics-Fonts Graphics-Primitives Graphics-Text Graphics-Transformations GraphicsTests-Files GraphicsTests-Primitives GraphicsTests-Text
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
Hello
NullEncoder is subclass of object ([1] for full hierachy). It is a superclass of Canvas.
What is the function of NullEncoder. No class comment so far?
Regards Hannes
[1] NullEncoder printHierarchy ' ProtoObject #() Object #() NullEncoder #(''target'' ''filterSelector'') FlattenEncoder #() ByteEncoder #() PrintableEncoder #() PostscriptEncoder #() PostscriptEncoderToDisk #() PropertyListEncoder #() Canvas #() ColorMappingCanvas #(''myCanvas'') AlphaBlendingCanvas #(''alpha'') ShadowDrawingCanvas #(''shadowColor'') FormCanvas #(''origin'' ''clipRect'' ''form'' ''port'' ''shadowColor'') BalloonCanvas #(''transform'' ''colorTransform'' ''engine'' ''aaLevel'' ''deferred'') BlueFormCanvas #() ColorPatchCanvas #(''stopMorph'' ''foundMorph'' ''doStop'') MultiResolutionCanvas #(''deferredMorphs'') PluggableCanvas #() BufferedCanvas #(''remote'' ''previousVersion'' ''lastTick'' ''dirtyRect'' ''mirrorOfScreen'') CachingCanvas #(''cacheCanvas'' ''mainCanvas'') ClippingCanvas #(''canvas'' ''clipRect'') MultiCanvas #(''canvases'' ''extent'' ''depth'') NullCanvas #() PostscriptCanvas #(''origin'' ''clipRect'' ''currentColor'' ''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack'' ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph'' ''initialScale'' ''savedMorphExtent'' ''currentTransformation'' ''printSpecs'' ''pages'') DSCPostscriptCanvas #() DSCPostscriptCanvasToDisk #() EPSCanvas #() RemoteCanvas #(''innerClipRect'' ''outerClipRect'' ''transform'' ''connection'' ''shadowColor'')'
And there is no 'FlattenEncoder' in Pharo 6.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
We have
NullEncoder FlattenEncoder Canvas
there are no direct users of NullEncoder and FlattenEncoder.
FlattenEncoder class comment is just
'The simplest possible encoding: leave the objects as is.'
a bit terse. Does not really say what the issue is about.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
P.S.
There is no NullEncoder in Pharo.
The class Canvas is not in a package 'Morphic-Support' but in a package 'Graphics-Canvas'.
There is no 'Graphics-Canvas' package in Squeak. [2]
Seems like a good idea to move Canvas and subclasses to a package 'Graphics-Canvas' as well.
[2] Graphics package in Squeak 6.0a-17405
Graphics-Display Objects Graphics-External-Ffenestri Graphics-Files Graphics-Fonts Graphics-Primitives Graphics-Text Graphics-Transformations GraphicsTests-Files GraphicsTests-Primitives GraphicsTests-Text
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
Hello
NullEncoder is subclass of object ([1] for full hierachy). It is a superclass of Canvas.
What is the function of NullEncoder. No class comment so far?
Regards Hannes
[1] NullEncoder printHierarchy ' ProtoObject #() Object #() NullEncoder #(''target'' ''filterSelector'') FlattenEncoder #() ByteEncoder #() PrintableEncoder #() PostscriptEncoder #() PostscriptEncoderToDisk #() PropertyListEncoder #() Canvas #() ColorMappingCanvas #(''myCanvas'') AlphaBlendingCanvas #(''alpha'') ShadowDrawingCanvas #(''shadowColor'') FormCanvas #(''origin'' ''clipRect'' ''form'' ''port'' ''shadowColor'') BalloonCanvas #(''transform'' ''colorTransform'' ''engine'' ''aaLevel'' ''deferred'') BlueFormCanvas #() ColorPatchCanvas #(''stopMorph'' ''foundMorph'' ''doStop'') MultiResolutionCanvas #(''deferredMorphs'') PluggableCanvas #() BufferedCanvas #(''remote'' ''previousVersion'' ''lastTick'' ''dirtyRect'' ''mirrorOfScreen'') CachingCanvas #(''cacheCanvas'' ''mainCanvas'') ClippingCanvas #(''canvas'' ''clipRect'') MultiCanvas #(''canvases'' ''extent'' ''depth'') NullCanvas #() PostscriptCanvas #(''origin'' ''clipRect'' ''currentColor'' ''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack'' ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph'' ''initialScale'' ''savedMorphExtent'' ''currentTransformation'' ''printSpecs'' ''pages'') DSCPostscriptCanvas #() DSCPostscriptCanvasToDisk #() EPSCanvas #() RemoteCanvas #(''innerClipRect'' ''outerClipRect'' ''transform'' ''connection'' ''shadowColor'')'
Hi Hannes
On 29.09.2017, at 15:21, H. Hirzel hannes.hirzel@gmail.com wrote:
And there is no 'FlattenEncoder' in Pharo 6
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
We have
NullEncoder FlattenEncoder Canvas
So here's the Thing: I looked in 3.8, and there's:
Object NullEncoder - Morphic-Postscript Filters FlattenEncoder - Morphic-Postscript Filters Canvas - Morphic-Support PostscriptCanvas - Morphic-Postscript Canvases
But also note that they all have a callback via class>>filterSelector:
NullEncoder>>filterSelector ^ #writeOnFilterStream: FlattenEncoder>>filterSelector ^ #flattenOnStream: Canvas>>filterSelector ^ #drawOnCanvas: PostscriptCanvas>>filterSelector ^ #fullDrawPostscriptOn:
I think part of that happened because this all shared common functionallity, In the sense that all those things "Put objects onto another thing with encoding inbetween". Thinking of things like a n-dimensonal stream or so…
I checked and It is like that even in Squeak 3.6, 3.0, 2.8. Squeak 1.13 does not have any of those, and it has no Morphic.
Self Morphic does not have such Encoders, tho.
In the end it all seems to be related to the PostScript Canvas, which, understandably, has to have access to certain objects and actually has to "encode" them into a file.
Best regards -Tobias
there are no direct users of NullEncoder and FlattenEncoder.
FlattenEncoder class comment is just
'The simplest possible encoding: leave the objects as is.'
a bit terse. Does not really say what the issue is about.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
P.S.
There is no NullEncoder in Pharo.
The class Canvas is not in a package 'Morphic-Support' but in a package 'Graphics-Canvas'.
There is no 'Graphics-Canvas' package in Squeak. [2]
Seems like a good idea to move Canvas and subclasses to a package 'Graphics-Canvas' as well.
[2] Graphics package in Squeak 6.0a-17405
Graphics-Display Objects Graphics-External-Ffenestri Graphics-Files Graphics-Fonts Graphics-Primitives Graphics-Text Graphics-Transformations GraphicsTests-Files GraphicsTests-Primitives GraphicsTests-Text
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
Hello
NullEncoder is subclass of object ([1] for full hierachy). It is a superclass of Canvas.
What is the function of NullEncoder. No class comment so far?
Regards Hannes
[1] NullEncoder printHierarchy ' ProtoObject #() Object #() NullEncoder #(''target'' ''filterSelector'') FlattenEncoder #() ByteEncoder #() PrintableEncoder #() PostscriptEncoder #() PostscriptEncoderToDisk #() PropertyListEncoder #() Canvas #() ColorMappingCanvas #(''myCanvas'') AlphaBlendingCanvas #(''alpha'') ShadowDrawingCanvas #(''shadowColor'') FormCanvas #(''origin'' ''clipRect'' ''form'' ''port'' ''shadowColor'') BalloonCanvas #(''transform'' ''colorTransform'' ''engine'' ''aaLevel'' ''deferred'') BlueFormCanvas #() ColorPatchCanvas #(''stopMorph'' ''foundMorph'' ''doStop'') MultiResolutionCanvas #(''deferredMorphs'') PluggableCanvas #() BufferedCanvas #(''remote'' ''previousVersion'' ''lastTick'' ''dirtyRect'' ''mirrorOfScreen'') CachingCanvas #(''cacheCanvas'' ''mainCanvas'') ClippingCanvas #(''canvas'' ''clipRect'') MultiCanvas #(''canvases'' ''extent'' ''depth'') NullCanvas #() PostscriptCanvas #(''origin'' ''clipRect'' ''currentColor'' ''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack'' ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph'' ''initialScale'' ''savedMorphExtent'' ''currentTransformation'' ''printSpecs'' ''pages'') DSCPostscriptCanvas #() DSCPostscriptCanvasToDisk #() EPSCanvas #() RemoteCanvas #(''innerClipRect'' ''outerClipRect'' ''transform'' ''connection'' ''shadowColor'')'
Tobias
You write that NullEncoder and subclasses could be summarized as
"Put objects onto another thing with encoding inbetween".
which I think is helpful for understanding.
Maybe we consider for the class comment of NullEncoder
"Put objects onto another thing with encoding/transformation inbetween".
But also note that this is not only related to PostscriptCanvas as we have
NullEncoder FlattenEncoder Canvas FormCanvas
FormCanvas has some nice usage examples.
#test1 is
test1 "FormCanvas test1"
| canvas | canvas := FormCanvas extent: 200@200. canvas fillColor: (Color black). canvas line: 10@10 to: 50@30 width: 1 color: (Color red). canvas frameRectangle: ((20@20) corner: (120@120)) width: 4 color: (Color green). canvas point: 100@100 color: (Color black). canvas drawString: 'Hello, World!' at: 40@40 font: nil color: (Color cyan). canvas fillRectangle: ((10@80) corner: (31@121)) color: (Color magenta). canvas fillOval: ((10@80) corner: (31@121)) color: (Color cyan). canvas frameOval: ((40@80) corner: (61@121)) color: (Color blue). canvas frameOval: ((70@80) corner: (91@121)) width: 3 color: (Color red alpha: 0.2). canvas fillRectangle: ((130@30) corner: (170@80)) color: (Color lightYellow). canvas showAt: 0@0.
This works fine in an MVC project
--Hannes
On 9/29/17, Tobias Pape Das.Linux@gmx.de wrote:
Hi Hannes
On 29.09.2017, at 15:21, H. Hirzel hannes.hirzel@gmail.com wrote:
And there is no 'FlattenEncoder' in Pharo 6
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
We have
NullEncoder FlattenEncoder Canvas
So here's the Thing: I looked in 3.8, and there's:
Object NullEncoder - Morphic-Postscript Filters FlattenEncoder - Morphic-Postscript Filters Canvas - Morphic-Support PostscriptCanvas - Morphic-Postscript Canvases
But also note that they all have a callback via class>>filterSelector:
NullEncoder>>filterSelector ^ #writeOnFilterStream: FlattenEncoder>>filterSelector ^ #flattenOnStream: Canvas>>filterSelector ^ #drawOnCanvas: PostscriptCanvas>>filterSelector ^ #fullDrawPostscriptOn:
I think part of that happened because this all shared common functionallity, In the sense that all those things "Put objects onto another thing with encoding inbetween". Thinking of things like a n-dimensonal stream or so…
I checked and It is like that even in Squeak 3.6, 3.0, 2.8. Squeak 1.13 does not have any of those, and it has no Morphic.
Self Morphic does not have such Encoders, tho.
In the end it all seems to be related to the PostScript Canvas, which, understandably, has to have access to certain objects and actually has to "encode" them into a file.
Best regards -Tobias
there are no direct users of NullEncoder and FlattenEncoder.
FlattenEncoder class comment is just
'The simplest possible encoding: leave the objects as is.'
a bit terse. Does not really say what the issue is about.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
P.S.
There is no NullEncoder in Pharo.
The class Canvas is not in a package 'Morphic-Support' but in a package 'Graphics-Canvas'.
There is no 'Graphics-Canvas' package in Squeak. [2]
Seems like a good idea to move Canvas and subclasses to a package 'Graphics-Canvas' as well.
[2] Graphics package in Squeak 6.0a-17405
Graphics-Display Objects Graphics-External-Ffenestri Graphics-Files Graphics-Fonts Graphics-Primitives Graphics-Text Graphics-Transformations GraphicsTests-Files GraphicsTests-Primitives GraphicsTests-Text
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
Hello
NullEncoder is subclass of object ([1] for full hierachy). It is a superclass of Canvas.
What is the function of NullEncoder. No class comment so far?
Regards Hannes
[1] NullEncoder printHierarchy ' ProtoObject #() Object #() NullEncoder #(''target'' ''filterSelector'') FlattenEncoder #() ByteEncoder #() PrintableEncoder #() PostscriptEncoder #() PostscriptEncoderToDisk #() PropertyListEncoder #() Canvas #() ColorMappingCanvas #(''myCanvas'') AlphaBlendingCanvas #(''alpha'') ShadowDrawingCanvas #(''shadowColor'') FormCanvas #(''origin'' ''clipRect'' ''form'' ''port'' ''shadowColor'') BalloonCanvas #(''transform'' ''colorTransform'' ''engine'' ''aaLevel'' ''deferred'') BlueFormCanvas #() ColorPatchCanvas #(''stopMorph'' ''foundMorph'' ''doStop'') MultiResolutionCanvas #(''deferredMorphs'') PluggableCanvas #() BufferedCanvas #(''remote'' ''previousVersion'' ''lastTick'' ''dirtyRect'' ''mirrorOfScreen'') CachingCanvas #(''cacheCanvas'' ''mainCanvas'') ClippingCanvas #(''canvas'' ''clipRect'') MultiCanvas #(''canvases'' ''extent'' ''depth'') NullCanvas #() PostscriptCanvas #(''origin'' ''clipRect'' ''currentColor'' ''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack'' ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph'' ''initialScale'' ''savedMorphExtent'' ''currentTransformation'' ''printSpecs'' ''pages'') DSCPostscriptCanvas #() DSCPostscriptCanvasToDisk #() EPSCanvas #() RemoteCanvas #(''innerClipRect'' ''outerClipRect'' ''transform'' ''connection'' ''shadowColor'')'
And also note that we have
Canvas subclass: #PostscriptCanvas
which is in another category 'MorphicExtras-Postscript Canvases'.
Not in the category 'Morphic-Support' in which NullEncoder and Canvas is.
And PostscriptCanvas is for the use in Morphic as it has an instance variable 'topLevelMorph'.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
Tobias
You write that NullEncoder and subclasses could be summarized as
"Put objects onto another thing with encoding inbetween".
which I think is helpful for understanding.
Maybe we consider for the class comment of NullEncoder
"Put objects onto another thing with encoding/transformation
inbetween".
But also note that this is not only related to PostscriptCanvas as we have
NullEncoder FlattenEncoder Canvas FormCanvas
FormCanvas has some nice usage examples.
#test1 is
test1 "FormCanvas test1"
| canvas | canvas := FormCanvas extent: 200@200. canvas fillColor: (Color black). canvas line: 10@10 to: 50@30 width: 1 color: (Color red). canvas frameRectangle: ((20@20) corner: (120@120)) width: 4 color: (Color green). canvas point: 100@100 color: (Color black). canvas drawString: 'Hello, World!' at: 40@40 font: nil color: (Color cyan). canvas fillRectangle: ((10@80) corner: (31@121)) color: (Color magenta). canvas fillOval: ((10@80) corner: (31@121)) color: (Color cyan). canvas frameOval: ((40@80) corner: (61@121)) color: (Color blue). canvas frameOval: ((70@80) corner: (91@121)) width: 3 color: (Color red alpha: 0.2). canvas fillRectangle: ((130@30) corner: (170@80)) color: (Color lightYellow). canvas showAt: 0@0.
This works fine in an MVC project
--Hannes
On 9/29/17, Tobias Pape Das.Linux@gmx.de wrote:
Hi Hannes
On 29.09.2017, at 15:21, H. Hirzel hannes.hirzel@gmail.com wrote:
And there is no 'FlattenEncoder' in Pharo 6
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
We have
NullEncoder FlattenEncoder Canvas
So here's the Thing: I looked in 3.8, and there's:
Object NullEncoder - Morphic-Postscript Filters FlattenEncoder - Morphic-Postscript Filters Canvas - Morphic-Support PostscriptCanvas - Morphic-Postscript Canvases
But also note that they all have a callback via class>>filterSelector:
NullEncoder>>filterSelector ^ #writeOnFilterStream: FlattenEncoder>>filterSelector ^ #flattenOnStream: Canvas>>filterSelector ^ #drawOnCanvas: PostscriptCanvas>>filterSelector ^ #fullDrawPostscriptOn:
I think part of that happened because this all shared common functionallity, In the sense that all those things "Put objects onto another thing with encoding inbetween". Thinking of things like a n-dimensonal stream or so…
I checked and It is like that even in Squeak 3.6, 3.0, 2.8. Squeak 1.13 does not have any of those, and it has no Morphic.
Self Morphic does not have such Encoders, tho.
In the end it all seems to be related to the PostScript Canvas, which, understandably, has to have access to certain objects and actually has to "encode" them into a file.
Best regards -Tobias
there are no direct users of NullEncoder and FlattenEncoder.
FlattenEncoder class comment is just
'The simplest possible encoding: leave the objects as is.'
a bit terse. Does not really say what the issue is about.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
P.S.
There is no NullEncoder in Pharo.
The class Canvas is not in a package 'Morphic-Support' but in a package 'Graphics-Canvas'.
There is no 'Graphics-Canvas' package in Squeak. [2]
Seems like a good idea to move Canvas and subclasses to a package 'Graphics-Canvas' as well.
[2] Graphics package in Squeak 6.0a-17405
Graphics-Display Objects Graphics-External-Ffenestri Graphics-Files Graphics-Fonts Graphics-Primitives Graphics-Text Graphics-Transformations GraphicsTests-Files GraphicsTests-Primitives GraphicsTests-Text
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
Hello
NullEncoder is subclass of object ([1] for full hierachy). It is a superclass of Canvas.
What is the function of NullEncoder. No class comment so far?
Regards Hannes
[1] NullEncoder printHierarchy ' ProtoObject #() Object #() NullEncoder #(''target'' ''filterSelector'') FlattenEncoder #() ByteEncoder #() PrintableEncoder #() PostscriptEncoder #() PostscriptEncoderToDisk #() PropertyListEncoder #() Canvas #() ColorMappingCanvas #(''myCanvas'') AlphaBlendingCanvas #(''alpha'') ShadowDrawingCanvas #(''shadowColor'') FormCanvas #(''origin'' ''clipRect'' ''form'' ''port'' ''shadowColor'') BalloonCanvas #(''transform'' ''colorTransform'' ''engine'' ''aaLevel'' ''deferred'') BlueFormCanvas #() ColorPatchCanvas #(''stopMorph'' ''foundMorph'' ''doStop'') MultiResolutionCanvas #(''deferredMorphs'') PluggableCanvas #() BufferedCanvas #(''remote'' ''previousVersion'' ''lastTick'' ''dirtyRect'' ''mirrorOfScreen'') CachingCanvas #(''cacheCanvas'' ''mainCanvas'') ClippingCanvas #(''canvas'' ''clipRect'') MultiCanvas #(''canvases'' ''extent'' ''depth'') NullCanvas #() PostscriptCanvas #(''origin'' ''clipRect'' ''currentColor'' ''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack'' ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph'' ''initialScale'' ''savedMorphExtent'' ''currentTransformation'' ''printSpecs'' ''pages'') DSCPostscriptCanvas #() DSCPostscriptCanvasToDisk #() EPSCanvas #() RemoteCanvas #(''innerClipRect'' ''outerClipRect'' ''transform'' ''connection'' ''shadowColor'')'
On 29.09.2017, at 17:50, H. Hirzel hannes.hirzel@gmail.com wrote:
And also note that we have
Canvas subclass: #PostscriptCanvas
which is in another category 'MorphicExtras-Postscript Canvases'.
Not in the category 'Morphic-Support' in which NullEncoder and Canvas is.
Yea, but it used to be different, only Canvas in Morphic-Support.
Object NullEncoder - Morphic-Postscript Filters FlattenEncoder - Morphic-Postscript Filters Canvas - Morphic-Support PostscriptCanvas - Morphic-Postscript Canvases
We would probably have to ask Dan or so on the whys and wherefores…
And PostscriptCanvas is for the use in Morphic as it has an instance variable 'topLevelMorph'.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
Tobias
You write that NullEncoder and subclasses could be summarized as
"Put objects onto another thing with encoding inbetween".
which I think is helpful for understanding.
Maybe we consider for the class comment of NullEncoder
"Put objects onto another thing with encoding/transformation inbetween".
But also note that this is not only related to PostscriptCanvas as we have
NullEncoder FlattenEncoder Canvas FormCanvas
FormCanvas has some nice usage examples.
#test1 is
test1 "FormCanvas test1"
| canvas | canvas := FormCanvas extent: 200@200. canvas fillColor: (Color black). canvas line: 10@10 to: 50@30 width: 1 color: (Color red). canvas frameRectangle: ((20@20) corner: (120@120)) width: 4 color: (Color green). canvas point: 100@100 color: (Color black). canvas drawString: 'Hello, World!' at: 40@40 font: nil color: (Color cyan). canvas fillRectangle: ((10@80) corner: (31@121)) color: (Color magenta). canvas fillOval: ((10@80) corner: (31@121)) color: (Color cyan). canvas frameOval: ((40@80) corner: (61@121)) color: (Color blue). canvas frameOval: ((70@80) corner: (91@121)) width: 3 color: (Color red alpha: 0.2). canvas fillRectangle: ((130@30) corner: (170@80)) color: (Color lightYellow). canvas showAt: 0@0.
This works fine in an MVC project
--Hannes
On 9/29/17, Tobias Pape Das.Linux@gmx.de wrote:
Hi Hannes
On 29.09.2017, at 15:21, H. Hirzel hannes.hirzel@gmail.com wrote:
And there is no 'FlattenEncoder' in Pharo 6
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
We have
NullEncoder FlattenEncoder Canvas
So here's the Thing: I looked in 3.8, and there's:
Object NullEncoder - Morphic-Postscript Filters FlattenEncoder - Morphic-Postscript Filters Canvas - Morphic-Support PostscriptCanvas - Morphic-Postscript Canvases
But also note that they all have a callback via class>>filterSelector:
NullEncoder>>filterSelector ^ #writeOnFilterStream: FlattenEncoder>>filterSelector ^ #flattenOnStream: Canvas>>filterSelector ^ #drawOnCanvas: PostscriptCanvas>>filterSelector ^ #fullDrawPostscriptOn:
I think part of that happened because this all shared common functionallity, In the sense that all those things "Put objects onto another thing with encoding inbetween". Thinking of things like a n-dimensonal stream or so…
I checked and It is like that even in Squeak 3.6, 3.0, 2.8. Squeak 1.13 does not have any of those, and it has no Morphic.
Self Morphic does not have such Encoders, tho.
In the end it all seems to be related to the PostScript Canvas, which, understandably, has to have access to certain objects and actually has to "encode" them into a file.
Best regards -Tobias
there are no direct users of NullEncoder and FlattenEncoder.
FlattenEncoder class comment is just
'The simplest possible encoding: leave the objects as is.'
a bit terse. Does not really say what the issue is about.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
P.S.
There is no NullEncoder in Pharo.
The class Canvas is not in a package 'Morphic-Support' but in a package 'Graphics-Canvas'.
There is no 'Graphics-Canvas' package in Squeak. [2]
Seems like a good idea to move Canvas and subclasses to a package 'Graphics-Canvas' as well.
[2] Graphics package in Squeak 6.0a-17405
Graphics-Display Objects Graphics-External-Ffenestri Graphics-Files Graphics-Fonts Graphics-Primitives Graphics-Text Graphics-Transformations GraphicsTests-Files GraphicsTests-Primitives GraphicsTests-Text
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote: > Hello > > NullEncoder is subclass of object ([1] for full hierachy). It is a > superclass of Canvas. > > What is the function of NullEncoder. No class comment so far? > > Regards > Hannes > > > ------------------------------------------------------------------------------------------------------------------------------- > > [1] NullEncoder printHierarchy ' > ProtoObject #() > Object #() > NullEncoder #(''target'' ''filterSelector'') > FlattenEncoder #() > ByteEncoder #() > PrintableEncoder #() > PostscriptEncoder #() > PostscriptEncoderToDisk #() > PropertyListEncoder #() > Canvas #() > ColorMappingCanvas #(''myCanvas'') > AlphaBlendingCanvas #(''alpha'') > ShadowDrawingCanvas #(''shadowColor'') > FormCanvas #(''origin'' ''clipRect'' ''form'' ''port'' > ''shadowColor'') > BalloonCanvas #(''transform'' ''colorTransform'' ''engine'' > ''aaLevel'' ''deferred'') > BlueFormCanvas #() > ColorPatchCanvas #(''stopMorph'' ''foundMorph'' ''doStop'') > MultiResolutionCanvas #(''deferredMorphs'') > PluggableCanvas #() > BufferedCanvas #(''remote'' ''previousVersion'' ''lastTick'' > ''dirtyRect'' ''mirrorOfScreen'') > CachingCanvas #(''cacheCanvas'' ''mainCanvas'') > ClippingCanvas #(''canvas'' ''clipRect'') > MultiCanvas #(''canvases'' ''extent'' ''depth'') > NullCanvas #() > PostscriptCanvas #(''origin'' ''clipRect'' ''currentColor'' > ''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack'' > ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph'' > ''initialScale'' ''savedMorphExtent'' ''currentTransformation'' > ''printSpecs'' ''pages'') > DSCPostscriptCanvas #() > DSCPostscriptCanvasToDisk #() > EPSCanvas #() > RemoteCanvas #(''innerClipRect'' ''outerClipRect'' ''transform'' > ''connection'' ''shadowColor'')' >
The target inst. var. is used exclusively by the PostscriptCanvas. And IMO it is a classical mistake of inheritance versus composition.
A PostScript canvas will have to encode the sequence of graphics instruction into a stream of PostScript instructions written into a PostScript file. For this purpose, it has a target PostscriptEncoder, which is itself an encoder already.
An Encoder implements a processing unit that transform a stream by using a kind of generic double dispatching.
Why the PostscriptCanvas has to be considered as an Encoder itself is very suspect, unless we ask
canvas write: aMorph.
Do we really want to do that, have a stream of Morphs (or other graphical objects)?
2017-09-29 17:33 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com:
Tobias
You write that NullEncoder and subclasses could be summarized as
"Put objects onto another thing with encoding inbetween".
which I think is helpful for understanding.
Maybe we consider for the class comment of NullEncoder
"Put objects onto another thing with encoding/transformation
inbetween".
But also note that this is not only related to PostscriptCanvas as we have
NullEncoder FlattenEncoder Canvas FormCanvas
FormCanvas has some nice usage examples.
#test1 is
test1 "FormCanvas test1"
| canvas | canvas := FormCanvas extent: 200@200. canvas fillColor: (Color black). canvas line: 10@10 to: 50@30 width: 1 color: (Color red). canvas frameRectangle: ((20@20) corner: (120@120)) width: 4 color:
(Color green). canvas point: 100@100 color: (Color black). canvas drawString: 'Hello, World!' at: 40@40 font: nil color: (Color cyan). canvas fillRectangle: ((10@80) corner: (31@121)) color: (Color magenta). canvas fillOval: ((10@80) corner: (31@121)) color: (Color cyan). canvas frameOval: ((40@80) corner: (61@121)) color: (Color blue). canvas frameOval: ((70@80) corner: (91@121)) width: 3 color: (Color red alpha: 0.2). canvas fillRectangle: ((130@30) corner: (170@80)) color: (Color lightYellow). canvas showAt: 0@0.
This works fine in an MVC project
--Hannes
On 9/29/17, Tobias Pape Das.Linux@gmx.de wrote:
Hi Hannes
On 29.09.2017, at 15:21, H. Hirzel hannes.hirzel@gmail.com wrote:
And there is no 'FlattenEncoder' in Pharo 6
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
We have
NullEncoder FlattenEncoder Canvas
So here's the Thing: I looked in 3.8, and there's:
Object NullEncoder - Morphic-Postscript Filters FlattenEncoder - Morphic-Postscript Filters Canvas - Morphic-Support PostscriptCanvas - Morphic-Postscript Canvases
But also note that they all have a callback via class>>filterSelector:
NullEncoder>>filterSelector ^ #writeOnFilterStream: FlattenEncoder>>filterSelector ^ #flattenOnStream: Canvas>>filterSelector ^ #drawOnCanvas: PostscriptCanvas>>filterSelector ^ #fullDrawPostscriptOn:
I think part of that happened because this all shared common
functionallity,
In the sense that all those things "Put objects onto another thing with encoding inbetween". Thinking of things like a n-dimensonal stream or so…
I checked and It is like that even in Squeak 3.6, 3.0, 2.8. Squeak 1.13 does not have any of those, and it has no Morphic.
Self Morphic does not have such Encoders, tho.
In the end it all seems to be related to the PostScript Canvas, which, understandably, has to have access to certain objects and actually has to "encode" them into a file.
Best regards -Tobias
there are no direct users of NullEncoder and FlattenEncoder.
FlattenEncoder class comment is just
'The simplest possible encoding: leave the objects as is.'
a bit terse. Does not really say what the issue is about.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
P.S.
There is no NullEncoder in Pharo.
The class Canvas is not in a package 'Morphic-Support' but in a package 'Graphics-Canvas'.
There is no 'Graphics-Canvas' package in Squeak. [2]
Seems like a good idea to move Canvas and subclasses to a package 'Graphics-Canvas' as well.
[2] Graphics package in Squeak 6.0a-17405
Graphics-Display Objects Graphics-External-Ffenestri Graphics-Files Graphics-Fonts Graphics-Primitives Graphics-Text Graphics-Transformations GraphicsTests-Files GraphicsTests-Primitives GraphicsTests-Text
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
Hello
NullEncoder is subclass of object ([1] for full hierachy). It is a superclass of Canvas.
What is the function of NullEncoder. No class comment so far?
Regards Hannes
[1] NullEncoder printHierarchy ' ProtoObject #() Object #() NullEncoder #(''target'' ''filterSelector'') FlattenEncoder #() ByteEncoder #() PrintableEncoder #() PostscriptEncoder #()
PostscriptEncoderToDisk #()
PropertyListEncoder #() Canvas #() ColorMappingCanvas #(''myCanvas'') AlphaBlendingCanvas
#(''alpha'')
ShadowDrawingCanvas
#(''shadowColor'')
FormCanvas #(''origin''
''clipRect'' ''form'' ''port''
''shadowColor'') BalloonCanvas
#(''transform'' ''colorTransform'' ''engine''
''aaLevel'' ''deferred'') BlueFormCanvas #() ColorPatchCanvas
#(''stopMorph'' ''foundMorph'' ''doStop'')
MultiResolutionCanvas
#(''deferredMorphs'')
PluggableCanvas #() BufferedCanvas
#(''remote'' ''previousVersion'' ''lastTick''
''dirtyRect'' ''mirrorOfScreen'') CachingCanvas
#(''cacheCanvas'' ''mainCanvas'')
ClippingCanvas
#(''canvas'' ''clipRect'')
MultiCanvas #(''canvases''
''extent'' ''depth'')
NullCanvas #() PostscriptCanvas #(''origin''
''clipRect'' ''currentColor''
''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack'' ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph'' ''initialScale'' ''savedMorphExtent'' ''currentTransformation'' ''printSpecs'' ''pages'') DSCPostscriptCanvas #()
DSCPostscriptCanvasToDisk #()
EPSCanvas #() RemoteCanvas #(''innerClipRect''
''outerClipRect'' ''transform''
''connection'' ''shadowColor'')'
For the question "Do we really want to do that, have a stream of Morphs (or other graphical objects)?" I think an interesting article to read is https://smalltalkrenaissance.wordpress.com/2015/06/29/silk-is-just-too-flexi...
A hierarchy of morphs (elements) may be regarded as well as a stream.
Canvas has a useful class comment [3]
It could be that NullEncoder FlattenEncoder are just helper classes to structure the code.
FlattenEncoder has the comment
"The simplest possible encoding: leave the objects as is."
Maybe the simplest thing for the class comment of NullEncoder is just to refer to the class comment of FlattenEncoder and Canvas.
[3] Class comment of 'Canvas' A canvas is a two-dimensional medium on which morphs are drawn in a device-independent manner. Canvases keep track of the origin and clipping rectangle, as well as the underlying drawing medium (such as a window, pixmap, or postscript script).
Subclasses must implement (at least) the following methods: * Drawing: #fillOval:color:borderWidth:borderColor: #frameAndFillRectangle:fillColor:borderWidth:borderColor: #drawPolygon:color:borderWidth:borderColor: #image:at:sourceRect:rule: #stencil:at:sourceRect:rule: #line:to:width:color: #paragraph:bounds:color: #text:bounds:font:color: * Support #clipBy:during: #translateBy:during: #translateBy:clippingTo:during: #transformBy:clippingTo:during:
On 9/29/17, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
The target inst. var. is used exclusively by the PostscriptCanvas. And IMO it is a classical mistake of inheritance versus composition.
A PostScript canvas will have to encode the sequence of graphics instruction into a stream of PostScript instructions written into a PostScript file. For this purpose, it has a target PostscriptEncoder, which is itself an encoder already.
An Encoder implements a processing unit that transform a stream by using a kind of generic double dispatching.
Why the PostscriptCanvas has to be considered as an Encoder itself is very suspect, unless we ask
canvas write: aMorph.
Do we really want to do that, have a stream of Morphs (or other graphical objects)?
2017-09-29 17:33 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com:
Tobias
You write that NullEncoder and subclasses could be summarized as
"Put objects onto another thing with encoding inbetween".
which I think is helpful for understanding.
Maybe we consider for the class comment of NullEncoder
"Put objects onto another thing with encoding/transformation
inbetween".
But also note that this is not only related to PostscriptCanvas as we have
NullEncoder FlattenEncoder Canvas FormCanvas
FormCanvas has some nice usage examples.
#test1 is
test1 "FormCanvas test1"
| canvas | canvas := FormCanvas extent: 200@200. canvas fillColor: (Color black). canvas line: 10@10 to: 50@30 width: 1 color: (Color red). canvas frameRectangle: ((20@20) corner: (120@120)) width: 4
color: (Color green). canvas point: 100@100 color: (Color black). canvas drawString: 'Hello, World!' at: 40@40 font: nil color: (Color cyan). canvas fillRectangle: ((10@80) corner: (31@121)) color: (Color magenta). canvas fillOval: ((10@80) corner: (31@121)) color: (Color cyan). canvas frameOval: ((40@80) corner: (61@121)) color: (Color blue). canvas frameOval: ((70@80) corner: (91@121)) width: 3 color: (Color red alpha: 0.2). canvas fillRectangle: ((130@30) corner: (170@80)) color: (Color lightYellow). canvas showAt: 0@0.
This works fine in an MVC project
--Hannes
On 9/29/17, Tobias Pape Das.Linux@gmx.de wrote:
Hi Hannes
On 29.09.2017, at 15:21, H. Hirzel hannes.hirzel@gmail.com wrote:
And there is no 'FlattenEncoder' in Pharo 6
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
We have
NullEncoder FlattenEncoder Canvas
So here's the Thing: I looked in 3.8, and there's:
Object NullEncoder - Morphic-Postscript Filters FlattenEncoder - Morphic-Postscript Filters Canvas - Morphic-Support PostscriptCanvas - Morphic-Postscript Canvases
But also note that they all have a callback via class>>filterSelector:
NullEncoder>>filterSelector ^ #writeOnFilterStream: FlattenEncoder>>filterSelector ^ #flattenOnStream: Canvas>>filterSelector ^ #drawOnCanvas: PostscriptCanvas>>filterSelector ^ #fullDrawPostscriptOn:
I think part of that happened because this all shared common
functionallity,
In the sense that all those things "Put objects onto another thing with encoding inbetween". Thinking of things like a n-dimensonal stream or so…
I checked and It is like that even in Squeak 3.6, 3.0, 2.8. Squeak 1.13 does not have any of those, and it has no Morphic.
Self Morphic does not have such Encoders, tho.
In the end it all seems to be related to the PostScript Canvas, which, understandably, has to have access to certain objects and actually has to "encode" them into a file.
Best regards -Tobias
there are no direct users of NullEncoder and FlattenEncoder.
FlattenEncoder class comment is just
'The simplest possible encoding: leave the objects as is.'
a bit terse. Does not really say what the issue is about.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
P.S.
There is no NullEncoder in Pharo.
The class Canvas is not in a package 'Morphic-Support' but in a package 'Graphics-Canvas'.
There is no 'Graphics-Canvas' package in Squeak. [2]
Seems like a good idea to move Canvas and subclasses to a package 'Graphics-Canvas' as well.
[2] Graphics package in Squeak 6.0a-17405
Graphics-Display Objects Graphics-External-Ffenestri Graphics-Files Graphics-Fonts Graphics-Primitives Graphics-Text Graphics-Transformations GraphicsTests-Files GraphicsTests-Primitives GraphicsTests-Text
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote: > Hello > > NullEncoder is subclass of object ([1] for full hierachy). It is a > superclass of Canvas. > > What is the function of NullEncoder. No class comment so far? > > Regards > Hannes > > > ------------------------------------------------------------
> > [1] NullEncoder printHierarchy ' > ProtoObject #() > Object #() > NullEncoder #(''target'' ''filterSelector'') > FlattenEncoder #() > ByteEncoder #() > PrintableEncoder #() > PostscriptEncoder #() >
PostscriptEncoderToDisk #()
> PropertyListEncoder #() > Canvas #() > ColorMappingCanvas > #(''myCanvas'') > AlphaBlendingCanvas
#(''alpha'')
> ShadowDrawingCanvas
#(''shadowColor'')
> FormCanvas #(''origin''
''clipRect'' ''form'' ''port''
> ''shadowColor'') > BalloonCanvas
#(''transform'' ''colorTransform'' ''engine''
> ''aaLevel'' ''deferred'') > BlueFormCanvas #() > ColorPatchCanvas
#(''stopMorph'' ''foundMorph'' ''doStop'')
> MultiResolutionCanvas
#(''deferredMorphs'')
> PluggableCanvas #() > BufferedCanvas
#(''remote'' ''previousVersion'' ''lastTick''
> ''dirtyRect'' ''mirrorOfScreen'') > CachingCanvas
#(''cacheCanvas'' ''mainCanvas'')
> ClippingCanvas
#(''canvas'' ''clipRect'')
> MultiCanvas > #(''canvases''
''extent'' ''depth'')
> NullCanvas #() > PostscriptCanvas #(''origin''
''clipRect'' ''currentColor''
> ''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack'' > ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph'' > ''initialScale'' ''savedMorphExtent'' ''currentTransformation'' > ''printSpecs'' ''pages'') > DSCPostscriptCanvas #() >
DSCPostscriptCanvasToDisk #()
> EPSCanvas #() > RemoteCanvas #(''innerClipRect''
''outerClipRect'' ''transform''
> ''connection'' ''shadowColor'')' >
2017-09-29 18:12 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com:
For the question "Do we really want to do that, have a stream of Morphs (or other graphical objects)?" I think an interesting article to read is https://smalltalkrenaissance.wordpress.com/2015/06/29/silk- is-just-too-flexible/
A hierarchy of morphs (elements) may be regarded as well as a stream.
Sorry, my question was bad. If streaming consist of a simple do: loop, an Encoder isn't really necessary. The right question is why would we need a generic stream transform pattern like Encoder is?
The canvas other than PostscriptCanvas don't use the target, they are sinks. So there's no reason to use an Encoder pattern here.
But PostscriptCanvas uses a different filterSelector. That means that we can differentiate drawing commands for some specific morph. And indeed, a BookMorph has a specific way to render on a PostscriptCanvas: it will render all the pages.
And a DSCPostscriptCanvas yet another: it will produces those Document Structuring Conventions which are meta informations on contents such as chapters, page numbers etc... encoded after double comments '%%'.
Thus using an Encoder permits a differentiation in rendering.
But I'm not at all convinced by this Encoder usage. It's not composable. What if I embed 1 or several BookMorph into another Morph? Won't the rendering and DSC be kind of broken?
What if we want to render this BookMorph with a specific target layout? Won't we need to recompose? Composing is more than rendering, so a Canvas would not be the right abstraction...
Rendering the whole book contents is a different operation specific to a BookMorph. It's not be a problem to have a specific menu/halo for this specific operation. This specific rendering is not composable. And maybe not the Canvas responsibility. So I don't see the point in using this Encoder pattern here.
Canvas has a useful class comment [3]
It could be that NullEncoder FlattenEncoder are just helper classes to structure the code.
FlattenEncoder has the comment
"The simplest possible encoding: leave the objects as is."
Maybe the simplest thing for the class comment of NullEncoder is just to refer to the class comment of FlattenEncoder and Canvas.
[3] Class comment of 'Canvas' A canvas is a two-dimensional medium on which morphs are drawn in a device-independent manner. Canvases keep track of the origin and clipping rectangle, as well as the underlying drawing medium (such as a window, pixmap, or postscript script).
Subclasses must implement (at least) the following methods: * Drawing: #fillOval:color:borderWidth:borderColor: #frameAndFillRectangle:fillColor:borderWidth:borderColor: #drawPolygon:color:borderWidth:borderColor: #image:at:sourceRect:rule: #stencil:at:sourceRect:rule: #line:to:width:color: #paragraph:bounds:color: #text:bounds:font:color: * Support #clipBy:during: #translateBy:during: #translateBy:clippingTo:during: #transformBy:clippingTo:during:
On 9/29/17, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
The target inst. var. is used exclusively by the PostscriptCanvas. And IMO it is a classical mistake of inheritance versus composition.
A PostScript canvas will have to encode the sequence of graphics instruction into a stream of PostScript instructions written into a PostScript file. For this purpose, it has a target PostscriptEncoder, which is itself an encoder already.
An Encoder implements a processing unit that transform a stream by using
a
kind of generic double dispatching.
Why the PostscriptCanvas has to be considered as an Encoder itself is
very
suspect, unless we ask
canvas write: aMorph.
Do we really want to do that, have a stream of Morphs (or other graphical objects)?
2017-09-29 17:33 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com:
Tobias
You write that NullEncoder and subclasses could be summarized as
"Put objects onto another thing with encoding inbetween".
which I think is helpful for understanding.
Maybe we consider for the class comment of NullEncoder
"Put objects onto another thing with encoding/transformation
inbetween".
But also note that this is not only related to PostscriptCanvas as we have
NullEncoder FlattenEncoder Canvas FormCanvas
FormCanvas has some nice usage examples.
#test1 is
test1 "FormCanvas test1"
| canvas | canvas := FormCanvas extent: 200@200. canvas fillColor: (Color black). canvas line: 10@10 to: 50@30 width: 1 color: (Color red). canvas frameRectangle: ((20@20) corner: (120@120)) width: 4
color: (Color green). canvas point: 100@100 color: (Color black). canvas drawString: 'Hello, World!' at: 40@40 font: nil color: (Color cyan). canvas fillRectangle: ((10@80) corner: (31@121)) color: (Color magenta). canvas fillOval: ((10@80) corner: (31@121)) color: (Color
cyan).
canvas frameOval: ((40@80) corner: (61@121)) color: (Color
blue).
canvas frameOval: ((70@80) corner: (91@121)) width: 3 color:
(Color red alpha: 0.2). canvas fillRectangle: ((130@30) corner: (170@80)) color: (Color lightYellow). canvas showAt: 0@0.
This works fine in an MVC project
--Hannes
On 9/29/17, Tobias Pape Das.Linux@gmx.de wrote:
Hi Hannes
On 29.09.2017, at 15:21, H. Hirzel hannes.hirzel@gmail.com wrote:
And there is no 'FlattenEncoder' in Pharo 6
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
We have
NullEncoder FlattenEncoder Canvas
So here's the Thing: I looked in 3.8, and there's:
Object NullEncoder - Morphic-Postscript Filters FlattenEncoder - Morphic-Postscript Filters Canvas - Morphic-Support PostscriptCanvas - Morphic-Postscript Canvases
But also note that they all have a callback via class>>filterSelector:
NullEncoder>>filterSelector ^ #writeOnFilterStream: FlattenEncoder>>filterSelector ^ #flattenOnStream: Canvas>>filterSelector ^ #drawOnCanvas: PostscriptCanvas>>filterSelector ^ #fullDrawPostscriptOn:
I think part of that happened because this all shared common
functionallity,
In the sense that all those things "Put objects onto another thing
with
encoding inbetween". Thinking of things like a n-dimensonal stream or so…
I checked and It is like that even in Squeak 3.6, 3.0, 2.8. Squeak 1.13 does not have any of those, and it has no Morphic.
Self Morphic does not have such Encoders, tho.
In the end it all seems to be related to the PostScript Canvas, which, understandably, has to have access to certain objects and actually has to "encode" them into a file.
Best regards -Tobias
there are no direct users of NullEncoder and FlattenEncoder.
FlattenEncoder class comment is just
'The simplest possible encoding: leave the objects as is.'
a bit terse. Does not really say what the issue is about.
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote: > P.S. > > There is no NullEncoder in Pharo. > > The class Canvas is not in a package 'Morphic-Support' but in a > package 'Graphics-Canvas'. > > There is no 'Graphics-Canvas' package in Squeak. [2] > > Seems like a good idea to move Canvas and subclasses to a package > 'Graphics-Canvas' as well. > > > [2] Graphics package in Squeak 6.0a-17405 > > Graphics-Display Objects > Graphics-External-Ffenestri > Graphics-Files > Graphics-Fonts > Graphics-Primitives > Graphics-Text > Graphics-Transformations > GraphicsTests-Files > GraphicsTests-Primitives > GraphicsTests-Text > > On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote: >> Hello >> >> NullEncoder is subclass of object ([1] for full hierachy). It is a >> superclass of Canvas. >> >> What is the function of NullEncoder. No class comment so far? >> >> Regards >> Hannes >> >> >> ------------------------------------------------------------
>> >> [1] NullEncoder printHierarchy ' >> ProtoObject #() >> Object #() >> NullEncoder #(''target'' ''filterSelector'') >> FlattenEncoder #() >> ByteEncoder #() >> PrintableEncoder #() >> PostscriptEncoder #() >>
PostscriptEncoderToDisk #()
>> PropertyListEncoder #() >> Canvas #() >> ColorMappingCanvas >> #(''myCanvas'') >> AlphaBlendingCanvas
#(''alpha'')
>> ShadowDrawingCanvas
#(''shadowColor'')
>> FormCanvas #(''origin''
''clipRect'' ''form'' ''port''
>> ''shadowColor'') >> BalloonCanvas
#(''transform'' ''colorTransform'' ''engine''
>> ''aaLevel'' ''deferred'') >> BlueFormCanvas #() >> ColorPatchCanvas
#(''stopMorph'' ''foundMorph'' ''doStop'')
>> MultiResolutionCanvas
#(''deferredMorphs'')
>> PluggableCanvas #() >> BufferedCanvas
#(''remote'' ''previousVersion'' ''lastTick''
>> ''dirtyRect'' ''mirrorOfScreen'') >> CachingCanvas
#(''cacheCanvas'' ''mainCanvas'')
>> ClippingCanvas
#(''canvas'' ''clipRect'')
>> MultiCanvas >> #(''canvases''
''extent'' ''depth'')
>> NullCanvas #() >> PostscriptCanvas #(''origin''
''clipRect'' ''currentColor''
>> ''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack'' >> ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph'' >> ''initialScale'' ''savedMorphExtent'' ''currentTransformation'' >> ''printSpecs'' ''pages'') >> DSCPostscriptCanvas #() >>
DSCPostscriptCanvasToDisk #()
>> EPSCanvas #() >> RemoteCanvas #(''innerClipRect''
''outerClipRect'' ''transform''
>> ''connection'' ''shadowColor'')' >> >
On Sep 29, 2017, at 19:09 , Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
The canvas other than PostscriptCanvas don't use the target, they are sinks.
That’s only technically true, and really an oversight. All canvases write their output somewhere, be it a bitmap, native display surface or other ‘DisplayMedium'. A canvas is a filter for converting morphs to this target ‘DisplayMedium’.
And having filter-canvases would be really cool :-)
Marcel
On 01.10.2017, at 11:38, Marcel Weiher marcel.weiher@gmail.com wrote:
On Sep 29, 2017, at 19:09 , Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
The canvas other than PostscriptCanvas don't use the target, they are sinks.
That’s only technically true, and really an oversight. All canvases write their output somewhere, be it a bitmap, native display surface or other ‘DisplayMedium'. A canvas is a filter for converting morphs to this target ‘DisplayMedium’.
And having filter-canvases would be really cool :-)
You mean like ColorMappingCanvas, AlphaBlendingCanvas, and ShadowDrawingCanvas? (Which, by your account, should not have an own myCanvas but rather reuse target…)?
Best regards -Tobias
Marcel
2017-10-01 12:57 GMT+02:00 Tobias Pape Das.Linux@gmx.de:
On 01.10.2017, at 11:38, Marcel Weiher marcel.weiher@gmail.com wrote:
On Sep 29, 2017, at 19:09 , Nicolas Cellier <
nicolas.cellier.aka.nice@gmail.com> wrote:
The canvas other than PostscriptCanvas don't use the target, they are
sinks.
That’s only technically true, and really an oversight. All canvases
write their output somewhere, be it a bitmap, native display surface or other ‘DisplayMedium'. A canvas is a filter for converting morphs to this target ‘DisplayMedium’.
And having filter-canvases would be really cool :-)
You mean like ColorMappingCanvas, AlphaBlendingCanvas, and ShadowDrawingCanvas? (Which, by your account, should not have an own myCanvas but rather reuse target…)?
Best regards -Tobias
Hi Marcel, Tobias, I perfectly understand what an Encoder is. OK I said it transforms stream instead of filters stream because I'm not academic enough ;). I agree that the pattern has a lot of potential, though parallelism still is a problem in Smalltalk processing model.
But: In a sense, the canvas did handle a stream of graphics instructions (draw a line, a circle, fill a rectangle etc...). Even, if we don't really reify those instructions, and tell (canvas write: (Line from: ... to: ....)) but rather use a more direct (canvas drawLineFrom:to:...) send. By making it an Encoder, it now handles both a stream of graphics instructions and a stream of objects (that can appropriately convert themselves to a stream of graphic instructions thru double dispatching). This is a metonymy.
I will repeat why it does not sound legitimate to me: First, a metonymy is obscuring responsibilities. Either that's an un-necessary indirection, because objects already know how to draw themselves, and it composes well already, because an object will ask the objects that it is composed of to render themselves. Or once we want to use it as a filter for a stream of arbitrary objects, we get a problem of composability (understand composing as giving a specific layout to the objects we want to render). So we have to give greater responsabilities to the dumb canvas for this composition to happen.
I showed that the only place where we make use of the double dispatching technic exhibit this problem of composability (we can't render in PostScript a Morph composed of BookMorph, because we can't put several pages into a page...).
If we really want to keep the Encoder pattern, then yes, we must use the target where possible. But I'm not convinced.
--------
Note about text rendering: we generally have to recompose the layout for different target (for example, if we want to render a BookMorph on A4 paper with specific margins...). For this composition to take place, we need to know the font metrics, and use some specific rules for margins, alignment, tab stops, etc... That's what a CompositionScanner does. I fail to see where those PostScript font metrics are in Squeak?
Rendering on PostScript is not an exception. If we are able to share some fonts then we can omit the composition step for most simple cases (like generating an EPS figure). But if we start with a bitmap font, rendering in PostScript will be very rough indeed.
For this reason, generating the PostScript in VW smalltalk goes thru a higher level indirection, the Document, which is somehow responsible for composing the layout for an arbitrary input stream of objects. It has to cooperate with a GraphicsContext (the quivalent of our Canvas) for transforming fonts to nearest PostScript equivalent, measuring, etc... VW has a PostScriptContext which is a specific GraphicsContext for low level rendering instructions, but that's not where everything takes place. The Document would handle the DSC for example (that sounds quite logical no?). Also note that a Document is not conceptually bound to a Postscript target, it could be anything, even LaTeX or Word backend, in which case it could eventually delegate the composition phase (which could work for a flow of text and small graphics, but would be more delicate for math expressions, tables and figures though).
Marcel
Hi Marcel, Tobias, I perfectly understand what an Encoder is. OK I said it transforms stream instead of filters stream because I'm not academic enough ;). I agree that the pattern has a lot of potential, though parallelism still is a problem in Smalltalk processing model.
For the potential, see my other message, which was delayed due to me sending it from the wrong account, it should have come before my answer to you. The model is mostly synchronous, so no parallelism, but some level of concurrent processing can be added and is useful for asynchronous programming (network stuff, for example).
But: In a sense, the canvas did handle a stream of graphics instructions (draw a line, a circle, fill a rectangle etc…).
Yep.
Even, if we don't really reify those instructions, and tell (canvas write: (Line from: ... to: ....)) but rather use a more direct (canvas drawLineFrom:to:...) send. By making it an Encoder, it now handles both a stream of graphics instructions and a stream of objects (that can appropriately convert themselves to a stream of graphic instructions thru double dispatching). This is a metonymy.
Not really. Having both a message-based and an object-based interface is somewhat common in this model, with the double dispatch deconstructing objects into sets of message-sends (with further object parameters) where necessary. But yes, that’s always a bit of a tension.
I will repeat why it does not sound legitimate to me: First, a metonymy is obscuring responsibilities. Either that's an un-necessary indirection, because objects already know how to draw themselves, and it composes well already, because an object will ask the objects that it is composed of to render themselves.
Of course the Canvas (and presumably other parts of the system) already follow this kind of pattern, as a pattern. The “Encoder” (I have struggled with naming, because it combines the role of a filter and a stream and some visitor-ish-ness), formalizes this pattern. The benefits are the usual ones: pluggability, documentation (if something is a subclass of X, I know what to expect), reuse, lower cognitive overhead, blah blah. But that would mean more widespread adoption, and considering the fact that this stuff has lingered in the image for 15+ years the need may just not be there..
Or once we want to use it as a filter for a stream of arbitrary objects, we get a problem of composability (understand composing as giving a specific layout to the objects we want to render).
Layout is not a responsibility of the canvas, the canvas needs to reproduce a layout that’s been created.
So we have to give greater responsabilities to the dumb canvas for this composition to happen.
I showed that the only place where we make use of the double dispatching technic exhibit this problem of composability (we can't render in PostScript a Morph composed of BookMorph, because we can't put several pages into a page…).
When I left it, a BookMorph would behave appropriately when embedded: it would “print” the visible page. Is that no longer the case? And having the “encoder” stick around is the way of remembering the top-level context even while adapting to specific objects in a nested hierarchy. Really quite similar to how super and self interact.
Note about text rendering: we generally have to recompose the layout for different target (for example, if we want to render a BookMorph on A4 paper with specific margins...). For this composition to take place, we need to know the font metrics, and use some specific rules for margins, alignment, tab stops, etc... That's what a CompositionScanner does. I fail to see where those PostScript font metrics are in Squeak?
If you recompose/reflow a text when printing, that’s a serious bug. This was a really long time ago, but IIRC fonts and font metrics were a significant problem.
Rendering on PostScript is not an exception. If we are able to share some fonts then we can omit the composition step for most simple cases (like generating an EPS figure). But if we start with a bitmap font, rendering in PostScript will be very rough indeed.
A “true WYSIWYG” approach would have been to encode the screen fonts as Type 3 bitmap fonts, or just dump the whole bitmap. But that would have sucked and wasn’t what Dan wanted. Dan wanted to have a “nice” printed version of the paper that had been composed in a BookMorph. Another would have been to have true printer compatible Type 1 fonts in Squeak. Yeah, right :-)
So I hacked it: I chose a set of Postscript fonts that were as close to an approximation of the look and metrics of the screen fonts used, concentrating the ones used in the paper. I also added a jshow command that would justify text on the printer, because the metrics obviously wouldn’t match perfectly. For justified text, that’s very noticeable.
The whole thing is decidedly “best effort” and was produced with a very specific goal and time-constraints. To do it right would have required massive changes to Squeak’s graphic subsystem, changes that were very much out of scope, and probably still are. That said, I did produce a version of Squeak that rendered its screen via roughly this mechanism on NeXT's DisplayPostscript. It was *epic*, but also pretty wonky, because of course the metrics didn’t match.
For this reason, generating the PostScript in VW smalltalk goes thru a higher level indirection, the Document, which is somehow responsible for composing the layout for an arbitrary input stream of objects.
It has to cooperate with a GraphicsContext (the quivalent of our Canvas) for transforming fonts to nearest PostScript equivalent, measuring, etc…
Transforming fonts is done on the class side of PostscriptCanvas, measuring is done in the printer when needed. Again, the additional infrastructure that would have been required to do this right would have been substantial, with an ongoing support burden and licensing headaches (AFM files etc.). And of course today the “correct” answer is to use the platform’s device-independent rendering API, which will take care of these sorts of problems. But that’s not the spirit of the system, last I checked.
VW has a PostScriptContext which is a specific GraphicsContext for low level rendering instructions, but that's not where everything takes place. The Document would handle the DSC for example (that sounds quite logical no?).
Document handling DSC? That sounds wrong, but I am not familiar with the details.
Also note that a Document is not conceptually bound to a Postscript target, it could be anything, even LaTeX or Word backend, in which case it could eventually delegate the composition phase (which could work for a flow of text and small graphics, but would be more delicate for math expressions, tables and figures though).
Yeah, again that’s at a whole different level.
Cheers,
Marcel
On Fri, Sep 29, 2017 at 04:37:16PM +0200, Tobias Pape wrote:
Hi Hannes
On 29.09.2017, at 15:21, H. Hirzel hannes.hirzel@gmail.com wrote:
And there is no 'FlattenEncoder' in Pharo 6
On 9/29/17, H. Hirzel hannes.hirzel@gmail.com wrote:
We have
NullEncoder FlattenEncoder Canvas
So here's the Thing: I looked in 3.8, and there's:
Object NullEncoder - Morphic-Postscript Filters FlattenEncoder - Morphic-Postscript Filters Canvas - Morphic-Support PostscriptCanvas - Morphic-Postscript Canvases
But also note that they all have a callback via class>>filterSelector:
NullEncoder>>filterSelector ^ #writeOnFilterStream: FlattenEncoder>>filterSelector ^ #flattenOnStream: Canvas>>filterSelector ^ #drawOnCanvas: PostscriptCanvas>>filterSelector ^ #fullDrawPostscriptOn:
I think part of that happened because this all shared common functionallity, In the sense that all those things "Put objects onto another thing with encoding inbetween". Thinking of things like a n-dimensonal stream or so???
I checked and It is like that even in Squeak 3.6, 3.0, 2.8. Squeak 1.13 does not have any of those, and it has no Morphic.
Self Morphic does not have such Encoders, tho.
In the end it all seems to be related to the PostScript Canvas, which, understandably, has to have access to certain objects and actually has to "encode" them into a file.
Best regards -Tobias
According to the update stream history at http://files.squeak.org/history, NullEncoder and friends were added in 1466EncodingFilters-MPW.cs by MPW:
Object subclass: #NullEncoder NullEncoder subclass: #FlattenEncoder FlattenEncoder subclass: #ByteEncoder ByteEncoder subclass: #PrintableEncoder PrintableEncoder subclass: #PrintEncoder PrintableEncoder subclass: #PropertyListEncoder PrintableEncoder subclass: #StoreEncoder
According to SqueakMap, MPW is Mark McCahill (mccahill@duke.edu).
According to Wikipedia, Mark McCahill at Duke is this guy: https://en.wikipedia.org/wiki/Mark_P._McCahill
According to the method time stamps, these classes date back to January 1901, so probably actually 2001.
Dave
On 30.09.2017, at 01:42, David T. Lewis lewis@mail.msen.com wrote:
According to the update stream history at http://files.squeak.org/history, NullEncoder and friends were added in 1466EncodingFilters-MPW.cs by MPW:
Object subclass: #NullEncoder NullEncoder subclass: #FlattenEncoder FlattenEncoder subclass: #ByteEncoder ByteEncoder subclass: #PrintableEncoder PrintableEncoder subclass: #PrintEncoder PrintableEncoder subclass: #PropertyListEncoder PrintableEncoder subclass: #StoreEncoder
According to SqueakMap, MPW is Mark McCahill (mccahill@duke.edu).
No, thats Marcel Weiher. He did a quite a lot Squeak/Postscript Stuff. I CC'ed him.
Marcel, can you comment on the Encoder Hierarchie? (Full thread here)
Best regards -Tobias
According to Wikipedia, Mark McCahill at Duke is this guy: https://en.wikipedia.org/wiki/Mark_P._McCahill
According to the method time stamps, these classes date back to January 1901, so probably actually 2001.
Dave
Tobias, thank you for referring to Marcel Weiher as the author of the Postscript support in Squeak. This helped me to find the following email with comments about the Encoder hierarchy
<citation> Marcel Weiher marcel.weiher@gmail.com Wed, Feb 27, 2013 at 9:14 PM To: The general-purpose Squeak developers list squeak-dev@lists.squeakfoundation.org
On Feb 25, 2013, at 20:22 , Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
Great, that confirms my own analyze. But the parallel hierarchy PrintEncoder StoreEncoder and PropertyListEncoder are presumably not used, and were just experiments right?
Pretty sure, yes.
</citation>
So it seems that
NullEncoder FlattenEncoder ByteEncoder PrintableEncoder
are a means to structure the code for the subclass PostscriptEncoder and thus to help to understand how the code works (see attached screen shot).
NullEncoder FlattenEncoder ByteEncoder PrintableEncoder PostscriptEncoder
Note that Canvas and thus then PostscriptCanvas is a subclass of FlattenEncoder. As Nicolas Cellier points out only PostscriptCanvas and subclasses use the NullEncoder and FlattenEncoder protocols. For example aMorph asEPS calls ^ EPSCanvas morphAsPostscript: self rotated: false. which at the end does ^target contents. which is implemented in NullEncoder.
The question thus is how much does PostScriptCanvas rely on the NullEncoder and FlattenEncoder protocols?
It might be quite easily possible to reimplement the necessary methods in PostScriptEncoder and then make Canvas a subclass of Object.
This will allow Canvas and subclasses to be put into a separate category 'Graphics-Canvas' in the base system.
PostScript support would then be something added on top of it.
To summarize: --------------------
The refactoring idea brought up for discussion is thus
1. Push the necessary NullEncoder and FlattenEncoder instance variable 'target' and the necessary methods down to PostscriptCanvas
2. Make Canvas a subclass of object thus separating then Encoder hierarchy from the Canvas hierarchy.
3. Put Canvas and some subclasses into a category 'Graphics-Canvas'
Regards
Hannes Hirzel
--Hannes
On 9/30/17, Tobias Pape Das.Linux@gmx.de wrote:
On 30.09.2017, at 01:42, David T. Lewis lewis@mail.msen.com wrote:
According to the update stream history at http://files.squeak.org/history, NullEncoder and friends were added in 1466EncodingFilters-MPW.cs by MPW:
Object subclass: #NullEncoder NullEncoder subclass: #FlattenEncoder FlattenEncoder subclass: #ByteEncoder ByteEncoder subclass: #PrintableEncoder PrintableEncoder subclass: #PrintEncoder PrintableEncoder subclass: #PropertyListEncoder PrintableEncoder subclass: #StoreEncoder
According to SqueakMap, MPW is Mark McCahill (mccahill@duke.edu).
No, thats Marcel Weiher. He did a quite a lot Squeak/Postscript Stuff. I CC'ed him.
Marcel, can you comment on the Encoder Hierarchie? (Full thread here)
Best regards -Tobias
According to Wikipedia, Mark McCahill at Duke is this guy: https://en.wikipedia.org/wiki/Mark_P._McCahill
According to the method time stamps, these classes date back to January 1901, so probably actually 2001.
Dave
The test case in EPSCanvasTest (introduced today with MorphicExtras-hjh.210.mcz)
shows what happens if you move
FlattenEncoder subclass: #Canvas
to Object subclass: Canvas
See comment there.
--Hannes
On 9/30/17, H. Hirzel hannes.hirzel@gmail.com wrote:
Tobias, thank you for referring to Marcel Weiher as the author of the Postscript support in Squeak. This helped me to find the following email with comments about the Encoder hierarchy
<citation> Marcel Weiher <marcel.weiher@gmail.com> Wed, Feb 27, 2013 at 9:14 PM To: The general-purpose Squeak developers list <squeak-dev@lists.squeakfoundation.org>
On Feb 25, 2013, at 20:22 , Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
Great, that confirms my own analyze. But the parallel hierarchy PrintEncoder StoreEncoder and PropertyListEncoder are presumably not used, and were just experiments right?
Pretty sure, yes.
</citation>
So it seems that
NullEncoder FlattenEncoder ByteEncoder PrintableEncoder
are a means to structure the code for the subclass PostscriptEncoder and thus to help to understand how the code works (see attached screen shot).
NullEncoder FlattenEncoder ByteEncoder PrintableEncoder PostscriptEncoder
Note that Canvas and thus then PostscriptCanvas is a subclass of FlattenEncoder. As Nicolas Cellier points out only PostscriptCanvas and subclasses use the NullEncoder and FlattenEncoder protocols. For example aMorph asEPS calls ^ EPSCanvas morphAsPostscript: self rotated: false. which at the end does ^target contents. which is implemented in NullEncoder.
The question thus is how much does PostScriptCanvas rely on the NullEncoder and FlattenEncoder protocols?
It might be quite easily possible to reimplement the necessary methods in PostScriptEncoder and then make Canvas a subclass of Object.
This will allow Canvas and subclasses to be put into a separate category 'Graphics-Canvas' in the base system.
PostScript support would then be something added on top of it.
To summarize:
The refactoring idea brought up for discussion is thus
- Push the necessary NullEncoder and FlattenEncoder instance variable
'target' and the necessary methods down to PostscriptCanvas
- Make Canvas a subclass of object thus separating then Encoder
hierarchy from the Canvas hierarchy.
- Put Canvas and some subclasses into a category 'Graphics-Canvas'
Regards
Hannes Hirzel
--Hannes
On 9/30/17, Tobias Pape Das.Linux@gmx.de wrote:
On 30.09.2017, at 01:42, David T. Lewis lewis@mail.msen.com wrote:
According to the update stream history at http://files.squeak.org/history, NullEncoder and friends were added in 1466EncodingFilters-MPW.cs by MPW:
Object subclass: #NullEncoder NullEncoder subclass: #FlattenEncoder FlattenEncoder subclass: #ByteEncoder ByteEncoder subclass: #PrintableEncoder PrintableEncoder subclass: #PrintEncoder PrintableEncoder subclass: #PropertyListEncoder PrintableEncoder subclass: #StoreEncoder
According to SqueakMap, MPW is Mark McCahill (mccahill@duke.edu).
No, thats Marcel Weiher. He did a quite a lot Squeak/Postscript Stuff. I CC'ed him.
Marcel, can you comment on the Encoder Hierarchie? (Full thread here)
Best regards -Tobias
According to Wikipedia, Mark McCahill at Duke is this guy: https://en.wikipedia.org/wiki/Mark_P._McCahill
According to the method time stamps, these classes date back to January 1901, so probably actually 2001.
Dave
On Sep 30, 2017, at 7:34 , Tobias Pape Das.Linux@gmx.de wrote:
No, thats Marcel Weiher. He did a quite a lot Squeak/Postscript Stuff. I CC'ed him.
Marcel, can you comment on the Encoder Hierarchie? (Full thread here)
Hi Tobias et al,
thanks for tagging me. :-)
The “Encoder” classes are a Squeak version of an “object oriented pipes and filters” system I implemented in Objective-C in the late 90s: https://github.com/mpw/MPWFoundation/tree/master/Streams.subproj https://github.com/mpw/MPWFoundation/tree/master/Streams.subproj
Why? Well, because the Postscript generation code was based on my Objective-C Postscript processing code (http://www.metaobject.com/Technology/#EGOS http://www.metaobject.com/Technology/#EGOS), which is heavily based on these filters.
I have found the filters to be incredibly useful over the last 20 years, partly because they compose so well: just like Unix pipes and filters, they are symmetric so that their input protocol ( #writeObject: ) is the same as their output protocol ( #writeObject:). The filterSelector is there to allow filter-specific processing using double dispatch, but once the processing is done the result is once again normalized to a #writeObject: You can therefore combine these filters any way you want.
Another feature is that they are, like Unix filters, fundamentally incremental, so multiple processing steps are interleaved and both input and output can stream directly to/from disk/network. When doing pre-press in the early 90ies (file sizes >> memory sizes) this was a useful feature, and it is still helpful today, see for example the first part of my UIKonf talk:
https://www.youtube.com/watch?v=kHG_zw75SjE
More recently, the fact that filters are dataflow-oriented and therefore don’t care much about the control flow has made them useful in implementing asynchronous processing pipelines Think “FRP” just simpler, more readable and faster. The Microsoft To-Do network stack is implemented using this.
With all the references to Unix P/F, it is probably no surprise that this also subsumes Unix I/O, just with the advantage of an OO hierarchy of shareable behavior. Oh, and also the interesting feature of subsuming both filters and (output) streams, so ‘stdout’ in Objective-Smalltalk is one of these, a ByteStream that knows how to serialize objects and output them to some target that expects bytes. And in ‘stsh’ it’s a slight variant of MPWByteStream that is more helpful to a human interacting.
On Sep 30, 2017, at 7:34 , Tobias Pape <Das.Linux@gmx.de mailto:Das.Linux@gmx.de> wrote:
No, thats Marcel Weiher. He did a quite a lot Squeak/Postscript Stuff. I CC'ed him.
Marcel, can you comment on the Encoder Hierarchie? (Full thread here)
Hi Tobias et al,
thanks for tagging me. :-)
The “Encoder” classes are a Squeak version of an “object oriented pipes and filters” system I implemented in Objective-C in the late 90s: https://github.com/mpw/MPWFoundation/tree/master/Streams.subproj https://github.com/mpw/MPWFoundation/tree/master/Streams.subproj
Why? Well, because the Postscript generation code was based on my Objective-C Postscript processing code (http://www.metaobject.com/Technology/#EGOS http://www.metaobject.com/Technology/#EGOS), which is heavily based on these filters.
I have found the filters to be incredibly useful over the last 20 years, partly because they compose so well: just like Unix pipes and filters, they are symmetric so that their input protocol ( #writeObject: ) is the same as their output protocol ( #writeObject:). The filterSelector is there to allow filter-specific processing using double dispatch, but once the processing is done the result is once again normalized to a #writeObject: You can therefore combine these filters any way you want.
Another feature is that they are, like Unix filters, fundamentally incremental, so multiple processing steps are interleaved and both input and output can stream directly to/from disk/network. When doing pre-press in the early 90ies (file sizes >> memory sizes) this was a useful feature, and it is still helpful today, see for example the first part of my UIKonf talk:
https://www.youtube.com/watch?v=kHG_zw75SjE https://www.youtube.com/watch?v=kHG_zw75SjE
More recently, the fact that filters are dataflow-oriented and therefore don’t care much about the control flow has made them useful in implementing asynchronous processing pipelines Think “FRP” just simpler, more readable and faster. The Microsoft To-Do network stack is implemented using this.
With all the references to Unix P/F, it is probably no surprise that this also subsumes Unix I/O, just with the advantage of an OO hierarchy of shareable behavior. Oh, and also the interesting feature of subsuming both filters and (output) streams, so ‘stdout’ in Objective-Smalltalk is one of these, a ByteStream that knows how to serialize objects and output them to some target that expects bytes. And in ‘stsh’ it’s a slight variant of MPWByteStream that is more helpful to a human interacting.
Hello Marcel, Nicolas, Tobias and Dave
Thank you Marcel W. for the illustrations and pointing out that the NullEncoder (figures now included [5]) implements a pipe/and filter hierarchy.
The video about app architectures [6] in which you describe different architecture styles is helpful. In particular you point out that the choice of a pipe/filter architecture has advantages in terms of memory consumption.
Tobias, you ask [the fact that some canvas subclasses do not use the 'target' object] <citation>
That’s only technically true, and really an oversight. All canvases write their output somewhere, be it a bitmap, native display surface or other ‘DisplayMedium'. A canvas is a filter for converting morphs to this target ‘DisplayMedium’.
And having filter-canvases would be really cool :-)
You mean like ColorMappingCanvas, AlphaBlendingCanvas, and ShadowDrawingCanvas? (Which, by your account, should not have an own myCanvas but rather reuse target…)? </citation>
My answer is that I do not see any benefit of using 'target' in these classes.
But Marcel Weiher gave as well an example of a more elaborate NullEncoder/FlattenEncoder/Canvas hierarchy to be used in a pipe/filter architecture style. [7]
So let's try to add more output classes to see how we can benefit from this architecture style.
Marcel Weiher noted in 1999 [8] <citation> [10 Sept 1999,MPW] The current MorphicPostscript support includes both EPS and multi-page Postscript generation.
BookMorphs generate multi-page files, all other Morphs generate an EPS ready for inclusion, though currently without a bitmap preview.
Postscript generation is split between a high-level class that maps Morphic drawing commands to Postscript imaging model commands and a low level class for generating actual Postscript code for the commands, in order to facilitate drop-in replacements for SPDF, SVG or comparable formats.
I also think this is a good base for supporting other device independent graphic models and even direct device independent drawing. </citation>
So the best thing to see how the mechanism / architecture works is actually to try out to add a few more "output encoders"
For example to render 1. a bookmorph (or just a series of morphs serving as 'slides') as a sequence of web pages or a series of slides in a presentation program, 2. a morph a SVG code 3. morphs as JSON descriptions to be used by a web services. 4. a sequence of morphs as a presentation for LibreOffice Impress export (LO Impress offers a 'flat XML format') 5. Powerpoint slides (zip archive generation needed)
I attach a demo / start of a MorphicHTMLCanvas implementation (Monticello mcz file). The description of the implementation steps are under [9].
The demo does not actually run but brings up the context where it shows that it is useful to have access to a 'target' object -- a HTML/CSS encoder - from within the morph hierarchy.
Run MorphicHTMLCanvas0Test new test01
The screen shot shows the method call hierarchy.
The demo does not show yet at which abstraction level in terms of "drawing commands"
aMorph fullDrawHTMLOn: self.
should operate. A more elaborate version of MorphicHTMLCanvas and a JSON example added will follow.
Kind regards Hannes
[5] NullEncoder http://wiki.squeak.org/squeak/5052
NullEncoder implements a filter
Object subclass: #NullEncoder instanceVariableNames: 'target filterSelector' classVariableNames: '' poolDictionaries: '' category: 'Morphic-Support'
[6] UIKonf 2017 – Day 1 – Marcel Weiher – High Performance App Architecture https://www.youtube.com/watch?v=kHG_zw75SjE
pipe/filter architecture at
minute 12:00, but 0:00..12:00 is useful to get the context - traditional call/return 'architecture' style
[7] Marcel Weiher -- http://forum.world.st/attachment/4974704/1/filterstream-hierarchy.pdf
[8] Squeak Postscript support http://wiki.squeak.org/squeak/753
-------------------------------------------------- [9] Implementation steps to create a HTML/CSS canvas for rendering morphs as a web code.
"1. create a canvas for rendering Morphs as HTML"
Canvas subclass: #MorphicHTMLCanvas0 instanceVariableNames: 'morphLevel' classVariableNames: '' poolDictionaries: '' category: 'Add-Ons-HTML0'
"2. create a test class for it"
TestCase subclass: #MorphicHTMLCanvas0Test instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Add-Ons-HTML0'
"3. Add an encoder to be used by MorphicHTMLCanvas0 for generating HTML/CSS"
PrintableEncoder subclass: #HTMLCSSEncoder0 instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Add-Ons-HTML0' "4a. Attach the HTMLCSSEncoder0 to the MorphicHTMLCanvas0" MorphicHTMLCanvas0 class
defaultTarget ^HTMLCSSEncoder0 stream
"4b. Add creation method" MorphicHTMLCanvas0 class
morphAsHTML: aMorph | htmlCanvas | htmlCanvas := self new. htmlCanvas reset. htmlCanvas fullDrawMorph: aMorph . ^htmlCanvas contents.
"4c. Add main method for rendering morphs as HTML"
MorphicHTMLCanvas0
fullDraw: aMorph aMorph fullDrawHTMLOn: self.
"5. within the Morph hierarchy implement messages to 'draw' morphs as HTML" Object fullDrawHTMLOn: aStream "do not do anything yet"
"6. Morph"
fullDrawHTMLOn: aCanvas
self halt.
"Here I can access
aCanvas target
and directly generate HTML and CSS code"
"7a. set up test environment " MorphicHTMLCanvas0Test test01
self assert: (MorphicHTMLCanvas0 morphAsHTML: self createTestMorph) notNil
"7b. an example morph for testing" MorphicHTMLCanvas0Test
createTestMorph "MorphicHTMLCanvas0Test new createTestMorph openInWorld" | slide | slide := RectangleMorph new extent: 800 @ 600; position: 10 @ 50; color: Color blue. slide addMorph: (RectangleMorph new extent: 100 @ 100; position: 20 @ 60; color: Color yellow). ^ slide
On 10/2/17, Marcel Weiher marcel.weiher@gmail.com wrote:
On Sep 30, 2017, at 7:34 , Tobias Pape <Das.Linux@gmx.de mailto:Das.Linux@gmx.de> wrote:
No, thats Marcel Weiher. He did a quite a lot Squeak/Postscript Stuff. I CC'ed him.
Marcel, can you comment on the Encoder Hierarchie? (Full thread here)
Hi Tobias et al,
thanks for tagging me. :-)
The “Encoder” classes are a Squeak version of an “object oriented pipes and filters” system I implemented in Objective-C in the late 90s: https://github.com/mpw/MPWFoundation/tree/master/Streams.subproj https://github.com/mpw/MPWFoundation/tree/master/Streams.subproj
Why? Well, because the Postscript generation code was based on my Objective-C Postscript processing code (http://www.metaobject.com/Technology/#EGOS http://www.metaobject.com/Technology/#EGOS), which is heavily based on these filters.
I have found the filters to be incredibly useful over the last 20 years, partly because they compose so well: just like Unix pipes and filters, they are symmetric so that their input protocol ( #writeObject: ) is the same as their output protocol ( #writeObject:). The filterSelector is there to allow filter-specific processing using double dispatch, but once the processing is done the result is once again normalized to a #writeObject: You can therefore combine these filters any way you want.
Another feature is that they are, like Unix filters, fundamentally incremental, so multiple processing steps are interleaved and both input and output can stream directly to/from disk/network. When doing pre-press in the early 90ies (file sizes >> memory sizes) this was a useful feature, and it is still helpful today, see for example the first part of my UIKonf talk:
https://www.youtube.com/watch?v=kHG_zw75SjE https://www.youtube.com/watch?v=kHG_zw75SjE
More recently, the fact that filters are dataflow-oriented and therefore don’t care much about the control flow has made them useful in implementing asynchronous processing pipelines Think “FRP” just simpler, more readable and faster. The Microsoft To-Do network stack is implemented using this.
With all the references to Unix P/F, it is probably no surprise that this also subsumes Unix I/O, just with the advantage of an OO hierarchy of shareable behavior. Oh, and also the interesting feature of subsuming both filters and (output) streams, so ‘stdout’ in Objective-Smalltalk is one of these, a ByteStream that knows how to serialize objects and output them to some target that expects bytes. And in ‘stsh’ it’s a slight variant of MPWByteStream that is more helpful to a human interacting.
Attached is an updated of the previous demo of a HTML export for Morphs.
2 classes - with a dozen of methods in total provides basic Morphic export by using the NullEncoder/Canvas hierarchy.
So far it shows a subclass of Canvas which makes use of the 'target' instance variable and where the combination of graphics command and write commands in this pipe and filter architecture is useful.
I implement fullDrawHTMLOn: in the Morph hierarchy following the fullDrawPostscriptOn:aCanvas example.
No support of borders and rounded corners yet. By making use of/overriding the existing drawOn: methods this should be possible.
HTML and CSS are not yet separated. In fact two encoders might be needed 1. HTMLEncoder 2. CSSEncoder which should work together. I am not sure yet how to handle this.
--Hannes
Note: Another example would be to have a "JSONCanvas" which generates morph descriptions in JSON.
On 10/2/17, H. Hirzel hannes.hirzel@gmail.com wrote:
Hello Marcel, Nicolas, Tobias and Dave
Thank you Marcel W. for the illustrations and pointing out that the NullEncoder (figures now included [5]) implements a pipe/and filter hierarchy.
The video about app architectures [6] in which you describe different architecture styles is helpful. In particular you point out that the choice of a pipe/filter architecture has advantages in terms of memory consumption.
Tobias, you ask [the fact that some canvas subclasses do not use the 'target' object]
<citation> > That’s only technically true, and really an oversight. All canvases > write their output somewhere, be it a bitmap, native display surface or > other ‘DisplayMedium'. A canvas is a filter for converting morphs to this > target ‘DisplayMedium’. > > And having filter-canvases would be really cool :-)
You mean like ColorMappingCanvas, AlphaBlendingCanvas, and ShadowDrawingCanvas? (Which, by your account, should not have an own myCanvas but rather reuse target…)?
</citation>
My answer is that I do not see any benefit of using 'target' in these classes.
But Marcel Weiher gave as well an example of a more elaborate NullEncoder/FlattenEncoder/Canvas hierarchy to be used in a pipe/filter architecture style. [7]
So let's try to add more output classes to see how we can benefit from this architecture style.
Marcel Weiher noted in 1999 [8]
<citation> [10 Sept 1999,MPW] The current MorphicPostscript support includes both EPS and multi-page Postscript generation.
BookMorphs generate multi-page files, all other Morphs generate an EPS ready for inclusion, though currently without a bitmap preview.
Postscript generation is split between a high-level class that maps Morphic drawing commands to Postscript imaging model commands and a low level class for generating actual Postscript code for the commands, in order to facilitate drop-in replacements for SPDF, SVG or comparable formats.
I also think this is a good base for supporting other device independent graphic models and even direct device independent drawing.
</citation>
So the best thing to see how the mechanism / architecture works is actually to try out to add a few more "output encoders"
For example to render
- a bookmorph (or just a series of morphs serving as 'slides') as a
sequence of web pages or a series of slides in a presentation program, 2. a morph a SVG code 3. morphs as JSON descriptions to be used by a web services. 4. a sequence of morphs as a presentation for LibreOffice Impress export (LO Impress offers a 'flat XML format') 5. Powerpoint slides (zip archive generation needed)
I attach a demo / start of a MorphicHTMLCanvas implementation (Monticello mcz file). The description of the implementation steps are under [9].
The demo does not actually run but brings up the context where it shows that it is useful to have access to a 'target' object -- a HTML/CSS encoder - from within the morph hierarchy.
Run MorphicHTMLCanvas0Test new test01
The screen shot shows the method call hierarchy.
The demo does not show yet at which abstraction level in terms of "drawing commands"
aMorph fullDrawHTMLOn: self.
should operate. A more elaborate version of MorphicHTMLCanvas and a JSON example added will follow.
Kind regards Hannes
[5] NullEncoder http://wiki.squeak.org/squeak/5052
NullEncoder implements a filter Object subclass: #NullEncoder instanceVariableNames: 'target filterSelector' classVariableNames: '' poolDictionaries: '' category: 'Morphic-Support'
[6] UIKonf 2017 – Day 1 – Marcel Weiher – High Performance App Architecture https://www.youtube.com/watch?v=kHG_zw75SjE
pipe/filter architecture at minute 12:00, but 0:00..12:00 is useful to get the context - traditional call/return 'architecture' style
[7] Marcel Weiher -- http://forum.world.st/attachment/4974704/1/filterstream-hierarchy.pdf
[8] Squeak Postscript support http://wiki.squeak.org/squeak/753
[9] Implementation steps to create a HTML/CSS canvas for rendering morphs as a web code.
"1. create a canvas for rendering Morphs as HTML"
Canvas subclass: #MorphicHTMLCanvas0
instanceVariableNames: 'morphLevel' classVariableNames: '' poolDictionaries: '' category: 'Add-Ons-HTML0'
"2. create a test class for it"
TestCase subclass: #MorphicHTMLCanvas0Test
instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Add-Ons-HTML0'
"3. Add an encoder to be used by MorphicHTMLCanvas0 for generating HTML/CSS"
PrintableEncoder subclass: #HTMLCSSEncoder0
instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Add-Ons-HTML0'
"4a. Attach the HTMLCSSEncoder0 to the MorphicHTMLCanvas0" MorphicHTMLCanvas0 class
defaultTarget
^HTMLCSSEncoder0 stream
"4b. Add creation method" MorphicHTMLCanvas0 class
morphAsHTML: aMorph | htmlCanvas | htmlCanvas := self new. htmlCanvas reset. htmlCanvas fullDrawMorph: aMorph .
^htmlCanvas contents.
"4c. Add main method for rendering morphs as HTML"
MorphicHTMLCanvas0 fullDraw: aMorph aMorph fullDrawHTMLOn: self.
"5. within the Morph hierarchy implement messages to 'draw' morphs as HTML" Object fullDrawHTMLOn: aStream "do not do anything yet"
"6. Morph"
fullDrawHTMLOn: aCanvas self halt. "Here I can access aCanvas target and directly generate HTML and CSS code"
"7a. set up test environment " MorphicHTMLCanvas0Test test01
self assert: (MorphicHTMLCanvas0 morphAsHTML: self createTestMorph)
notNil
"7b. an example morph for testing" MorphicHTMLCanvas0Test
createTestMorph
"MorphicHTMLCanvas0Test new createTestMorph openInWorld" | slide | slide := RectangleMorph new extent: 800 @ 600; position: 10 @ 50; color: Color blue. slide addMorph: (RectangleMorph new extent: 100 @ 100; position: 20 @ 60; color: Color yellow). ^ slide
On 10/2/17, Marcel Weiher marcel.weiher@gmail.com wrote:
On Sep 30, 2017, at 7:34 , Tobias Pape <Das.Linux@gmx.de mailto:Das.Linux@gmx.de> wrote:
No, thats Marcel Weiher. He did a quite a lot Squeak/Postscript Stuff. I CC'ed him.
Marcel, can you comment on the Encoder Hierarchie? (Full thread here)
Hi Tobias et al,
thanks for tagging me. :-)
The “Encoder” classes are a Squeak version of an “object oriented pipes and filters” system I implemented in Objective-C in the late 90s: https://github.com/mpw/MPWFoundation/tree/master/Streams.subproj https://github.com/mpw/MPWFoundation/tree/master/Streams.subproj
Why? Well, because the Postscript generation code was based on my Objective-C Postscript processing code (http://www.metaobject.com/Technology/#EGOS http://www.metaobject.com/Technology/#EGOS), which is heavily based on these filters.
I have found the filters to be incredibly useful over the last 20 years, partly because they compose so well: just like Unix pipes and filters, they are symmetric so that their input protocol ( #writeObject: ) is the same as their output protocol ( #writeObject:). The filterSelector is there to allow filter-specific processing using double dispatch, but once the processing is done the result is once again normalized to a #writeObject: You can therefore combine these filters any way you want.
Another feature is that they are, like Unix filters, fundamentally incremental, so multiple processing steps are interleaved and both input and output can stream directly to/from disk/network. When doing pre-press in the early 90ies (file sizes >> memory sizes) this was a useful feature, and it is still helpful today, see for example the first part of my UIKonf talk:
https://www.youtube.com/watch?v=kHG_zw75SjE https://www.youtube.com/watch?v=kHG_zw75SjE
More recently, the fact that filters are dataflow-oriented and therefore don’t care much about the control flow has made them useful in implementing asynchronous processing pipelines Think “FRP” just simpler, more readable and faster. The Microsoft To-Do network stack is implemented using this.
With all the references to Unix P/F, it is probably no surprise that this also subsumes Unix I/O, just with the advantage of an OO hierarchy of shareable behavior. Oh, and also the interesting feature of subsuming both filters and (output) streams, so ‘stdout’ in Objective-Smalltalk is one of these, a ByteStream that knows how to serialize objects and output them to some target that expects bytes. And in ‘stsh’ it’s a slight variant of MPWByteStream that is more helpful to a human interacting.
squeak-dev@lists.squeakfoundation.org