Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.postscript > #2861 > unrolled thread

Getting Rid Of PostScript

Started byLawrence D’Oliveiro <lawrencedo99@gmail.com>
First post2016-10-05 18:24 -0700
Last post2016-10-19 17:15 -0700
Articles 20 on this page of 42 — 10 participants

Back to article view | Back to comp.lang.postscript


Contents

  Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-05 18:24 -0700
    Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-06 14:50 -0700
    Re: Getting Rid Of PostScript jdaw1 <jdawiseman@gmail.com> - 2016-10-06 15:45 -0700
      Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-06 17:44 -0700
      Re: Getting Rid Of PostScript Mark Carroll <mtbc@bcs.org> - 2016-10-07 08:47 +0100
        Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-07 15:08 -0700
          Re: Getting Rid Of PostScript luser droog <luser.droog@gmail.com> - 2016-10-07 18:47 -0700
          Re: Getting Rid Of PostScript Mark Carroll <mtbc@bcs.org> - 2016-10-08 12:34 +0100
    Re: Getting Rid Of PostScript luser droog <luser.droog@gmail.com> - 2016-10-07 18:39 -0700
      Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-07 19:07 -0700
        Re: Getting Rid Of PostScript luser droog <luser.droog@gmail.com> - 2016-10-12 15:32 -0700
          Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-12 17:06 -0700
          Re: Getting Rid Of PostScript rodd@panix.com (Rod Dorman) - 2016-10-13 19:07 +0000
            Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-13 15:02 -0700
              Re: Getting Rid Of PostScript rodd@panix.com (Rod Dorman) - 2016-10-14 20:13 +0000
                Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-14 14:39 -0700
                Re: Getting Rid Of PostScript Martin Leese <please@see.Web.for.e-mail.INVALID> - 2016-10-16 10:40 -0600
                  Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-17 18:06 -0700
                    Re: Getting Rid Of PostScript Alan <alan.isaac@gmail.com> - 2016-10-17 18:44 -0700
                      Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-17 22:43 -0700
                        Re: Getting Rid Of PostScript Martin Leese <please@see.Web.for.e-mail.INVALID> - 2016-10-18 10:13 -0600
                          Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-18 15:28 -0700
                          Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-18 15:35 -0700
                            Re: Getting Rid Of PostScript Ross Presser <rpresser@gmail.com> - 2016-10-18 23:05 -0700
                              Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-10-19 19:23 +0200
                                Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-19 17:17 -0700
                                  Re: Getting Rid Of PostScript Ross Presser <rpresser@gmail.com> - 2016-10-21 09:18 -0700
                                    Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-21 18:10 -0700
                                Re: Getting Rid Of PostScript Ross Presser <rpresser@gmail.com> - 2016-10-21 09:14 -0700
                            Re: Getting Rid Of PostScript Markus Triska <triska@metalevel.at> - 2016-10-19 20:55 +0200
                              Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-19 17:57 -0700
                                Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-24 16:54 -0700
                                  Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-10-25 16:26 +0200
                                    Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-25 10:32 -0700
                                      Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-10-25 21:06 +0200
                                        Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-11-14 15:15 -0800
                                          Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-11-16 00:17 +0100
                                            Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-11-21 18:37 +0100
                                              Re: Getting Rid Of PostScript Carlos <angus@quovadis.com.ar> - 2016-11-21 18:39 +0100
                                  Re: Getting Rid Of PostScript Markus Triska <triska@metalevel.at> - 2016-10-25 20:52 +0200
                        Re: Getting Rid Of PostScript Alan <alan.isaac@gmail.com> - 2016-10-19 16:41 -0700
                          Re: Getting Rid Of PostScript Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-10-19 17:15 -0700

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#2904

FromMartin Leese <please@see.Web.for.e-mail.INVALID>
Date2016-10-18 10:13 -0600
Message-ID<nu5hm5$k6i$1@dont-email.me>
In reply to#2903
Lawrence D’Oliveiro wrote:
> On Tuesday, October 18, 2016 at 2:44:24 PM UTC+13, Alan wrote:
>> On Monday, October 17, 2016 at 9:07:05 PM UTC-4, Lawrence D’Oliveiro wrote:
>>
>>> PostScript still wouldn’t be as good a graphics language as Python.
>> I don't even know what this claim means.
> 
> It means what it says.

The key is the definition of "good".  If you
define good to mean "supported by Adobe" then
the answer becomes clear.  Other definitions
lead to different answers.  Different
computer languages have different strengths
and weaknesses.  Discussions about which are
good, better or best go nowhere.

-- 
Regards,
Martin Leese
E-mail: please@see.Web.for.e-mail.INVALID
Web: http://members.tripod.com/martin_leese/

[toc] | [prev] | [next] | [standalone]


#2905

FromLawrence D’Oliveiro <lawrencedo99@gmail.com>
Date2016-10-18 15:28 -0700
Message-ID<ea302921-8502-4ec3-9832-41234dea194c@googlegroups.com>
In reply to#2904
On Wednesday, October 19, 2016 at 5:13:15 AM UTC+13, Martin Leese wrote:
>
> On Monday, October 17, 2016 at 9:07:05 PM UTC-4, Lawrence D’Oliveiro wrote:
>
>> PostScript still wouldn’t be as good a graphics language as Python.
> 
> The key is the definition of "good".

“Good” as in “fit for purpose”.  For example, here is an elementary example: computing a fillet arc at a corner between two intersecting straight lines: <http://default-cube.deviantart.com/art/Fillet-631797773>.

In the Python code <https://github.com/ldo/qahirah_examples/blob/master/fillet>, the lines are defined by three points p0, p1 and p2, so they intersect at p1. Given the radius r of the fillet circle, we need to compute two points, t1 and t2, where the fillet arc is tangent to the lines. Having computed “inset” (the distance of t1 and t2 from p1), determining t1 and t2 is quite easy, e.g.:

        t1 = p1 + Vector.unit((p0 - p1).angle()) * inset

This is because Python lets me define a “Vector” type in my Cairo binding (which Cairo itself does not have!), complete with a full set of corresponding arithmetic operations, so that I can compute both the x- and y-coordinate of a point in a single formula.

PostScript has no such type, so at a minimum you would have to write out the above formula twice, once for each coordinate. On top of having to write out your own formulas for computing vector directions.

[toc] | [prev] | [next] | [standalone]


#2906

FromLawrence D’Oliveiro <lawrencedo99@gmail.com>
Date2016-10-18 15:35 -0700
Message-ID<effed4e0-4474-44f0-b9c8-1c28cd17b95c@googlegroups.com>
In reply to#2904
On Wednesday, October 19, 2016 at 5:13:15 AM UTC+13, Martin Leese wrote:
> If you define good to mean "supported by Adobe" then
> the answer becomes clear.

What becomes clear is that PostScript is hardly “supported” by Adobe any more. The company itself thinks its fortunes now lie elsewhere. Look at the forlorn wishlist accumulating in the “PostScript desiderata” thread; look also at the bugs people keep finding with Distiller, that have gone unfixed for so long.

Basically, the only implementation of PostScript still worth using is Ghostscript. Is PostScript itself still worth using? Only for backward compatibility; not for anything new.

[toc] | [prev] | [next] | [standalone]


#2907

FromRoss Presser <rpresser@gmail.com>
Date2016-10-18 23:05 -0700
Message-ID<4bf74c64-049f-436d-b19d-0a5b2e41883b@googlegroups.com>
In reply to#2906
On Tuesday, October 18, 2016 at 6:35:39 PM UTC-4, Lawrence
D’Oliveiro wrote:
> Basically, the only implementation of PostScript still worth using
> is Ghostscript. Is PostScript itself still worth using? Only for
> backward compatibility; not for anything new.

I continue to be confused as to why you are proseletyzing against
Postscript in a group named comp.lang.postscript. The group isn't
named comp.lang.kill-all-postscript-lovers. Can you take it
elsewhere, or are you congentially incapable of leaving people to
their own enthusiasms?

[toc] | [prev] | [next] | [standalone]


#2908

FromCarlos <angus@quovadis.com.ar>
Date2016-10-19 19:23 +0200
Message-ID<20161019192339.28665fad@samara.DOMA>
In reply to#2907
[Ross Presser <rpresser@gmail.com>, 2016-10-18 23:05]
> On Tuesday, October 18, 2016 at 6:35:39 PM UTC-4, Lawrence
> D’Oliveiro wrote:
> > Basically, the only implementation of PostScript still worth using
> > is Ghostscript. Is PostScript itself still worth using? Only for
> > backward compatibility; not for anything new.  
> 
> I continue to be confused as to why you are proseletyzing against
> Postscript in a group named comp.lang.postscript. The group isn't
> named comp.lang.kill-all-postscript-lovers. Can you take it
> elsewhere, or are you congentially incapable of leaving people to
> their own enthusiasms?

I disagree. I think criticism of PostScript and negative opinions should
be welcome, especially when they are founded. In my case, they don't
diminish my enthusiasm about the language at all. But in any case, by
request, he's mainly restricting criticism to this thread, so if you
don't like to read it, why don't you just ignore the thread? Any
newsreader should have that capability.

-- 

[toc] | [prev] | [next] | [standalone]


#2912

FromLawrence D’Oliveiro <lawrencedo99@gmail.com>
Date2016-10-19 17:17 -0700
Message-ID<f5ce2ffa-83a1-454e-8144-b231532c8e62@googlegroups.com>
In reply to#2908
On Thursday, October 20, 2016 at 6:24:13 AM UTC+13, Carlos wrote:
>
> ... why don't you just ignore the thread?

Which, of course, the trolls are never going to do.

You can tell they are trolls: they love to criticize and complain about others, yet they cannot actually offer any evidence (such as working code) in support of their criticisms.

For example, consider that I began this thread by offering examples of code, with and without using PostScript, to show how the latter was so much simpler than the former. Yet it seems nobody has paid the slightest bit of notice.

[toc] | [prev] | [next] | [standalone]


#2915

FromRoss Presser <rpresser@gmail.com>
Date2016-10-21 09:18 -0700
Message-ID<c067bacb-1e54-42a2-9994-768017f6861a@googlegroups.com>
In reply to#2912
On Wednesday, October 19, 2016 at 8:17:17 PM UTC-4, Lawrence
D’Oliveiro wrote:
> On Thursday, October 20, 2016 at 6:24:13 AM UTC+13, Carlos wrote:
> >
> > ... why don't you just ignore the thread?
> 
> Which, of course, the trolls are never going to do.
> 
> You can tell they are trolls: they love to criticize and complain
> about others, yet they cannot actually offer any evidence (such as
> working code) in support of their criticisms.

You seem to have a misunderstanding of the word "troll". Perhaps 
you are trying to refer to people who dislike your preference. That
is not a troll. A troll is one who posts outrageous or inflammatory
language solely to watch the fireworks spread. I am not trolling. I
admit I am complaining. I am not trolling.

> For example, consider that I began this thread by offering
> examples of code, with and without using PostScript, to show how
> the latter was so much simpler than the former. Yet it seems
> nobody has paid the slightest bit of notice.

Nobody has paid the slightest bit of notice because practically
nobody is interested. You have a hobby horse: you want people to
use Python and Cairo instead of Postscript. That's interesting in
its own right. But declaring that Postscript *MUST* *BE* *ABANDONED*
in favor of your hobby horse just doesn't make good conversation.

[toc] | [prev] | [next] | [standalone]


#2917

FromLawrence D’Oliveiro <lawrencedo99@gmail.com>
Date2016-10-21 18:10 -0700
Message-ID<97412cc8-8144-49cc-a4b2-aba860ff6445@googlegroups.com>
In reply to#2915
On Saturday, October 22, 2016 at 5:18:16 AM UTC+13, Ross Presser wrote:
>
> On Wednesday, October 19, 2016 at 8:17:17 PM UTC-4, Lawrence
> D’Oliveiro wrote:
>
>> You can tell they are trolls: they love to criticize and complain
>> about others, yet they cannot actually offer any evidence (such as
>> working code) in support of their criticisms.
> 
> You seem to have a misunderstanding of the word "troll".

Well, somebody who posts just to say “I’m not interested in reading what you post” would seem to fit the bill.

> Nobody has paid the slightest bit of notice because practically
> nobody is interested.

I rest my case.

[toc] | [prev] | [next] | [standalone]


#2914

FromRoss Presser <rpresser@gmail.com>
Date2016-10-21 09:14 -0700
Message-ID<08b471b2-48e5-40d0-b1af-f25414484d60@googlegroups.com>
In reply to#2908
On Wednesday, October 19, 2016 at 1:24:13 PM UTC-4, Carlos wrote:
> But in any case, by
> request, he's mainly restricting criticism to this thread, so if you
> don't like to read it, why don't you just ignore the thread? Any
> newsreader should have that capability.

Well, his discouragement was all over every thread. If he's stopped 
spreading it around so much then it's not so objectionable. 

[toc] | [prev] | [next] | [standalone]


#2909

FromMarkus Triska <triska@metalevel.at>
Date2016-10-19 20:55 +0200
Message-ID<m2bmyg6ue8.fsf@metalevel.at>
In reply to#2906
Lawrence D’Oliveiro <lawrencedo99@gmail.com> writes:

> Look at the forlorn wishlist accumulating in the “PostScript
> desiderata” thread; look also at the bugs people keep finding with
> Distiller, that have gone unfixed for so long.

This is not the first time that a deep need is not met. For example,
there was a similar problem with version control systems for decades:
No good system even remotely in sight. Then, after decades, suddenly
several amazing contenders entered the scene, and one of them changed
the landscape significantly. In my view, the last word on this is not
yet spoken, and until this is all fixed, a list is nice to have.

> Basically, the only implementation of PostScript still worth using is
> Ghostscript. Is PostScript itself still worth using? Only for backward
> compatibility; not for anything new.

That is not my experience at all. For example, only recently I wanted to
typeset the cycle graph C_{100} for a scientific publication. Space was
tight, much like in the lines of this paragraph. I wanted a layout that
showed:

   -) the *number* of each node
   -) the *weight* of each node, either 1 or -1
   -) whether the node is part of a kernel.

A few simple PostScript definitions sufficed to let me quickly and
easily experiment with many different layouts of this graph and the
variants I needed.

In this case and many others like it, PostScript was invaluable to me to
quickly try different layouts, using a suitable domain-specific language
that I implemented within PostScript itself.

If you want to try this yourself, here is the data I visualized:

The nodes (of 1..100 in total) that constitute the kernel:

    1 3 6 9 12 15 18 20 23 25 27 30 33 36 39 41 43 46 48 51 54 57 60 63 66
    68 71 73 75 78 80 83 86 89 92 95 97 99

The weight of each node, as a PostScript array:

    /weights [-1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1
      1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 1 -1 -1
      1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1 1 1
      -1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 -1 1 -1] def

And yes, I indirectly used GhostScript to easily inspect these layouts.
I say "indirectly" because I actually previewed these graphs directly
within Emacs (where I also wrote the PostScript code), which uses
GhostScript to convert the PostScript file to a PNG file which is then
displayed within Emacs. Personally, I have no need for a second program
that does the same as GhostScript, so a single implementation of
PostScript is sufficient for me and no argument against the language.

All the best,
Markus

[toc] | [prev] | [next] | [standalone]


#2913

FromLawrence D’Oliveiro <lawrencedo99@gmail.com>
Date2016-10-19 17:57 -0700
Message-ID<68890a35-ae58-4755-b6be-5f8a7d4b0362@googlegroups.com>
In reply to#2909
On Thursday, October 20, 2016 at 7:55:31 AM UTC+13, Markus Triska wrote:
> Lawrence D’Oliveiro writes:
> 
>> Basically, the only implementation of PostScript still worth using is
>> Ghostscript. Is PostScript itself still worth using? Only for backward
>> compatibility; not for anything new.
> 
> That is not my experience at all.

You agree with the first part, though: the only implementation still worth using is Ghostscript.

> For example, only recently I wanted to
> typeset the cycle graph C_{100} for a scientific publication. Space was
> tight, much like in the lines of this paragraph. I wanted a layout that
> showed:
> 
>    -) the *number* of each node
>    -) the *weight* of each node, either 1 or -1
>    -) whether the node is part of a kernel.
> 
> A few simple PostScript definitions sufficed to let me quickly and
> easily experiment with many different layouts of this graph and the
> variants I needed.
> 
> In this case and many others like it, PostScript was invaluable to me to
> quickly try different layouts, using a suitable domain-specific language
> that I implemented within PostScript itself.
>
> And yes, I indirectly used GhostScript to easily inspect these layouts.
> I say "indirectly" because I actually previewed these graphs directly
> within Emacs (where I also wrote the PostScript code), which uses
> GhostScript to convert the PostScript file to a PNG file which is then
> displayed within Emacs.

I use Emacs too, but not for that. For this kind of graphical visualization, I prefer to use Jupyter with the IPython kernel.

First, some definitions to create and manage a drawing surface:

    from IPython.display import \
        display_png
    import qahirah as qah
    from qahirah import \
        CAIRO, \
        Colour, \
        Matrix, \
        Path, \
        Rect, \
        Vector

    pix = qah.ImageSurface.create \
      (
        format = CAIRO.FORMAT_RGB24,
        dimensions = (400, 400)
      )
    ctx = None

    def reset() :
        "(re)initializes the drawing context, wiping out any existing drawing."
        global ctx
        del ctx
        ctx = qah.Context.create(pix)
        (ctx
            .save()
            .set_source_colour(Colour.grey(.95))
            .paint()
            .restore()
            .select_font_face("sens serif", CAIRO.FONT_SLANT_NORMAL, CAIRO.FONT_WEIGHT_NORMAL)
        )
    #end reset

    def display() :
        "(re)displays what has been drawn."
        display_png(pix.to_png_bytes(), raw = True)
    #end display

The data you provided, converted to Python form:

    kernel = \
        {
            1, 3, 6, 9, 12, 15, 18, 20, 23, 25,
            27, 30, 33, 36, 39, 41, 43, 46, 48, 51,
            54, 57, 60, 63, 66, 68, 71, 73, 75, 78,
            80, 83, 86, 89, 92, 95, 97, 99,
        }

    weights = \
        [
            -1, -1, 1, -1, 1, 1, -1, -1, 1, 1,
            -1, 1, -1, -1, 1, -1, 1, 1, -1, 1,
            -1, -1, 1, 1, -1, -1, 1, -1, 1, 1,
            -1, -1, 1, 1, -1, 1, -1, -1, 1, 1,
            -1, -1, 1, -1, 1, 1, -1, 1, -1, -1,
            1, -1, 1, 1, -1, -1, 1, 1, -1, 1,
            -1, -1, 1, -1, 1, 1, -1, 1, -1, -1,
            1, 1, -1, -1, 1, -1, 1, 1, -1, 1,
            -1, -1, 1, -1, 1, 1, -1, -1, 1, 1,
            -1, 1, -1, -1, 1, 1, -1, -1, 1, -1,
        ]

    def in_kernel(node_nr) :
        "node_nr is in [1 .. 100]."
        return \
            (node_nr - 1) in kernel
    #end in_kernel

    def get_weight(node_nr) :
        "node_nr is in [1 .. 100]."
        return \
            weights[node_nr - 1]
    #end get_weight

Here is an example routine which, given a “draw_node” action that actually draws each node, lays them out in a square grid:

    def draw_nodes_grid(draw_node) :
        reset()
        cell_dims = pix.dimensions / Vector(10, 10)
        for row in range(10) :
            for col in range(10) :
                node_nr = row * 10 + col + 1
                bounds = Rect.from_corners((0, 0), cell_dims) + cell_dims * Vector(col, row)
                ctx.save()
                draw_node(ctx, bounds, node_nr)
                ctx.restore()
            #end col
        #end for
        display()
    #end draw_nodes_grid

Here is an initial stab at a node-drawing routine: “make_draw_node_1” creates the actual routine, given four colours to indicate the state of being in the kernel or not, or having a positive or negative weight.

    def make_draw_node_1(in_kernel_colour, not_kernel_colour, pos_weight_colour, neg_weight_colour) :

        def draw_node(g,  bounds, nr) :
            fill_colour = (not_kernel_colour, in_kernel_colour)[in_kernel(nr)]
            border_colour = {-1 : neg_weight_colour, 1 : pos_weight_colour}[get_weight(nr)]
            (g
                .set_source_colour(fill_colour)
                .new_path()
                .rectangle(bounds)
                .fill()
                .set_source_colour(border_colour)
                .set_line_width(3)
                .rectangle(bounds.inset((1.5, 1.5)))
                .stroke()
            )
            label = "%d" % nr
            label_extents = g.text_extents(label)
            (g
                .set_font_size(12)
                .move_to(bounds.middle + Vector(- label_extents.x_bearing - label_extents.advance.x / 2, label_extents.height / 2))
                .show_text(label)
            )
        #end draw_node

        return \
            draw_node
    #end make_draw_node_1

The actual drawing of the graphic is done with a sequence like

    example_draw_node = make_draw_node_1 \
      (
        in_kernel_colour = Colour.from_hsva((0.5, 0.5, 0.9, 1)),
        not_kernel_colour = Colour.from_hsva((0, 0, 0, 0)),
        pos_weight_colour = Colour.from_hsva((0, 0, 0, 1)),
        neg_weight_colour = Colour.from_hsva((0, 0, 0.5, 1)),
      )
    draw_nodes_grid(example_draw_node)

You can see how you can use that as a starting point for further layout and rendering experiments.

Another thing you can do with IPython is add interactive “widgets” to cell output: this way, the user can drag sliders etc which your function can interpret as variable parameters and redraw the graphics.

[toc] | [prev] | [next] | [standalone]


#2921

FromLawrence D’Oliveiro <lawrencedo99@gmail.com>
Date2016-10-24 16:54 -0700
Message-ID<66538ba6-282f-4b3d-b8ba-94b93903385f@googlegroups.com>
In reply to#2913
On Thursday, October 20, 2016 at 1:58:00 PM UTC+13, I wrote some Python code. It is worth pointing out some salient features of this code, that take advantage of the advanced capabilities of Python.

>     def draw_nodes_grid(draw_node) :

Note that the actual drawing of a node is implemented by the “draw_node” function which is passed as the argument, while “draw_nodes_grid” itself only implements the layout of the entire diagram.

>         reset()
>         cell_dims = pix.dimensions / Vector(10, 10)

See how the x- and y-dimensions of a single cell are computed from the dimensions of the drawing area by a single division?

>         for row in range(10) :
>             for col in range(10) :
>                 node_nr = row * 10 + col + 1
>                 bounds = Rect.from_corners((0, 0), cell_dims) + cell_dims * Vector(col, row)

And here we have the bounds of a cell computed from the row and column number, again both x- and y-coordinates determined in a single expression.

>     def make_draw_node_1(in_kernel_colour, not_kernel_colour, pos_weight_colour, neg_weight_colour) :
> 
>         def draw_node(g,  bounds, nr) :
>             ....
>         #end draw_node
> 
>         return \
>             draw_node
>     #end make_draw_node_1

Here we have a function returning a function. Each invocation of the outer function returns a new instance of the inner function; each instance can have different values for the arguments passed to the outer function, and will refer to its own values for those arguments, independent of any other instance. This is called “lexical binding”, and is an essential part of treating functions as first-class objects.

>     example_draw_node = make_draw_node_1 \
>       (
>         in_kernel_colour = Colour.from_hsva((0.5, 0.5, 0.9, 1)),
>         not_kernel_colour = Colour.from_hsva((0, 0, 0, 0)),
>         pos_weight_colour = Colour.from_hsva((0, 0, 0, 1)),
>         neg_weight_colour = Colour.from_hsva((0, 0, 0.5, 1)),
>       )
>     draw_nodes_grid(example_draw_node)

Here the diagram is generated with one particular draw_node function using one particular colour scheme.

Would anybody like to try doing this in PostScript? It would take at least twice as much work. And it still wouldn’t be interactive.

[toc] | [prev] | [next] | [standalone]


#2922

FromCarlos <angus@quovadis.com.ar>
Date2016-10-25 16:26 +0200
Message-ID<nunq2l$cib$1@dont-email.me>
In reply to#2921
On 25/10/2016 1:54, Lawrence D’Oliveiro wrote:
> On Thursday, October 20, 2016 at 1:58:00 PM UTC+13, I wrote some
> Python code. It is worth pointing out some salient features of this
> code, that take advantage of the advanced capabilities of Python.

I don't think anything you showed here demonstrated any advanced
capabilities of Python (at least not with respect to PostScript).

>>     def draw_nodes_grid(draw_node) :
>
> Note that the actual drawing of a node is implemented by the
> “draw_node” function which is passed as the argument, while
> “draw_nodes_grid” itself only implements the layout of the entire
> diagram.

You can do that in PostScript, too. Pass a block to a procedure, then
call it with exec.

>>         reset()
>>         cell_dims = pix.dimensions / Vector(10, 10)
>
> See how the x- and y-dimensions of a single cell are computed from
> the dimensions of the drawing area by a single division?

Come on. Just because you wrote a vector library in Python and not in
PostScript, that doesn't make Python better.

   /celldims pix /dimensions get 10 10 Vector Vdiv def

assuming pix is a dictionary. Here is the start of a vector library:

   /Vector { 2 packedarray } bind def
   /x      { 0 get         } bind def
   /y      { 1 get         } bind def
   /xy     { aload pop     } bind def

   /Vop    { 3 1 roll
             xy 3 -1 roll xy
             3 -1 roll 4 index exec
             3 1 roll exch 3 index exec
             exch Vector
             exch pop      } bind def

   /Vdiv   { { div } Vop   } bind def

>>         for row in range(10) :
>>             for col in range(10) :
>>                 node_nr = row * 10 + col + 1
>>                 bounds = Rect.from_corners((0, 0), cell_dims) + cell_dims * Vector(col, row)
>
> And here we have the bounds of a cell computed from the row and
> column number, again both x- and y-coordinates determined in a
> single expression.

   0 1 9 { /row exch def        % for
     0 1 9 { /col exch def      % for
       /nodenr row 10 mul col add 1 add def
       /bounds 0 0 Vector celldims Rectfromcorners
               celldims col row Vector Vmul
               Radd
       def
       ...
     } for
   } for

Again, a matter of libraries

   /Vmul   { { mul } Vop   } bind def
   /Vadd   { { add } Vop   } bind def
   /Vsub   { { sub } Vop   } bind def

   /min    { 2 copy gt { exch } if pop } bind def
   /max    { 2 copy lt { exch } if pop } bind def

   /Rect   { 4 packedarray } bind def
   /width  { 2 get         } bind def
   /height { 3 get         } bind def
   /w+h    { dup width exch height } bind def

   /Rectfromcorners {
       2 copy { min } Vop
       3 1 roll { max } Vop
       1 index Vsub
       exch xy 3 -1 roll xy Rect
   } bind def

   /Radd {
       1 index x  2 index y Vector Vadd xy
       3 -1 roll w+h Rect
   } bind def


>>     def make_draw_node_1(in_kernel_colour, not_kernel_colour, pos_weight_colour, neg_weight_colour) :
>>
>>         def draw_node(g,  bounds, nr) :
>>             ....
>>         #end draw_node
>>
>>         return \
>>             draw_node
>>     #end make_draw_node_1
>
> Here we have a function returning a function. Each invocation of the
> outer function returns a new instance of the inner function; each
> instance can have different values for the arguments passed to the
> outer function, and will refer to its own values for those
> arguments, independent of any other instance. This is called
> “lexical binding”, and is an essential part of treating functions as
> first-class objects.

That's a facility the Python compiler provides because it's otherwise
impossible to return custom functions. You don't need the
interpreter's help in PostScript, because procedures are arrays, and
you can easily create arrays programmatically. (By the way, this is a
recurring topic in this newsgroup lately.)

So, again, it's just a matter of libraries. (Although I don't think
you could do it in Python with just a library.)

Try this:
   /makeadder {
       1 dict begin
       /n exch def
       { n add } bindcurrent
       end
   } bind def

And then "4 makeadder ==".

Here is a couple procedures that let you do that:

   % copies array recursively
   % <array> -> <new array>
   /deepcopy {
       dup xcheck exch
       dup length array copy
       dup length 1 sub 0 exch 1 exch { % for       % a i
           2 copy 2 copy get dup type
           dup /arraytype eq exch /packedarraytype eq or % a i a i e ?
           { % ifelse
               deepcopy put
           }
           {
               pop pop pop
           } ifelse
           pop
       } for
       exch { cvx } if
   } bind def

   % recursively replaces elements in <array> found in <dict>
   % <array> <dict> -> -
   /replaceall {
       1 index length 1 sub  0 1  3 -1 roll { % for 0 1 length-1
           3 copy  3 -1 roll  exch    % a d i d a i
           get                        % a d i d e
           2 copy known               % a d i d e ?
           % ifelse
           {                          % a d i d e
               get                    % a d i v
               3 index  3 1 roll      % a d a i v
               put
           } % else
           {                          % a d i d e
               dup type /arraytype eq % a d i d e ?
               { exch replaceall }
               { pop pop } ifelse
               pop
           } ifelse                   % a d
       } for
       pop pop
   } bind def

   % bind names existing in currentdict
   % proc -> proc
   /bindcurrent {
       deepcopy dup currentdict replaceall
   } bind def

>>     example_draw_node = make_draw_node_1 \
>>       (
>>         in_kernel_colour = Colour.from_hsva((0.5, 0.5, 0.9, 1)),
>>         not_kernel_colour = Colour.from_hsva((0, 0, 0, 0)),
>>         pos_weight_colour = Colour.from_hsva((0, 0, 0, 1)),
>>         neg_weight_colour = Colour.from_hsva((0, 0, 0.5, 1)),
>>       )
>>     draw_nodes_grid(example_draw_node)
>
> Here the diagram is generated with one particular draw_node function
> using one particular colour scheme.
>
> Would anybody like to try doing this in PostScript? It would take at
> least twice as much work. And it still wouldn’t be interactive.

I don't think it would take more work than doing it in Python,
assuming you already have the libraries. I think everybody agrees that
Cairo, the library, allows you to do things for which, apparently,
there isn't a PostScript library yet. But nothing you wrote proves
that Python, the programming language, is more capable than PostScript.

-- 

[toc] | [prev] | [next] | [standalone]


#2923

FromLawrence D’Oliveiro <lawrencedo99@gmail.com>
Date2016-10-25 10:32 -0700
Message-ID<41c5fbb5-a268-4cc1-8522-73f92980ce69@googlegroups.com>
In reply to#2922
On Wednesday, October 26, 2016 at 3:26:52 AM UTC+13, Carlos wrote:
>
> On 25/10/2016 1:54, Lawrence D’Oliveiro wrote:
>
>> Note that the actual drawing of a node is implemented by the
>> “draw_node” function which is passed as the argument, while
>> “draw_nodes_grid” itself only implements the layout of the entire
>> diagram.
> 
> You can do that in PostScript, too. Pass a block to a procedure, then
> call it with exec.

But you don’t get the lexical binding, which is what really makes them useful.

>>         cell_dims = pix.dimensions / Vector(10, 10)
>>>
>> See how the x- and y-dimensions of a single cell are computed from
>> the dimensions of the drawing area by a single division?
> 
> Come on. Just because you wrote a vector library in Python and not in
> PostScript, that doesn't make Python better.

You didn’t notice that the operation was done with the standard division operator, then? Python allows you to define custom overloads for the standard operators. This way, you can write your expressions using notation much closer to the original maths.

> assuming pix is a dictionary. Here is the start of a vector library:
> 
>    /Vector { 2 packedarray } bind def
>    /x      { 0 get         } bind def
>    /y      { 1 get         } bind def
>    /xy     { aload pop     } bind def
> 
>    /Vop    { 3 1 roll
>              xy 3 -1 roll xy
>              3 -1 roll 4 index exec
>              3 1 roll exch 3 index exec
>              exch Vector
>              exch pop      } bind def
> 
>    /Vdiv   { { div } Vop   } bind def

Not much of a start, don’t you think <https://groups.google.com/d/msg/comp.lang.postscript/fEyXR90-wq4/AsOwYiltBgAJ>?

> Again, a matter of libraries

Which PostScript is, frankly, no help with.

> [Lexical binding is] a facility the Python compiler provides because it's
> otherwise impossible to return custom functions. You don't need the
> interpreter's help in PostScript, because procedures are arrays, and
> you can easily create arrays programmatically. (By the way, this is a
> recurring topic in this newsgroup lately.)

But you cannot do the lexical binding. Not in a reentrant fashion.

> Try this:

How many lines of PostScript code have you written so far? Compare it to how many lines of Python code I needed to write. And your solution isn’t even complete yet.

[toc] | [prev] | [next] | [standalone]


#2925

FromCarlos <angus@quovadis.com.ar>
Date2016-10-25 21:06 +0200
Message-ID<20161025210647.55ecd219@samara.DOMA>
In reply to#2923
[Lawrence D’Oliveiro <lawrencedo99@gmail.com>, 2016-10-25 10:32]
> On Wednesday, October 26, 2016 at 3:26:52 AM UTC+13, Carlos wrote:
> >
> > On 25/10/2016 1:54, Lawrence D’Oliveiro wrote:
> >  
> >> Note that the actual drawing of a node is implemented by the
> >> “draw_node” function which is passed as the argument, while
> >> “draw_nodes_grid” itself only implements the layout of the entire
> >> diagram.  
> > 
> > You can do that in PostScript, too. Pass a block to a procedure,
> > then call it with exec.  
> 
> But you don’t get the lexical binding, which is what really makes
> them useful.

You can get the PostScript equivalent, as previously explained (more
below).

> >>         cell_dims = pix.dimensions / Vector(10, 10)  
> >>>  
> >> See how the x- and y-dimensions of a single cell are computed from
> >> the dimensions of the drawing area by a single division?  
> > 
> > Come on. Just because you wrote a vector library in Python and not
> > in PostScript, that doesn't make Python better.  
> 
> You didn’t notice that the operation was done with the standard
> division operator, then? Python allows you to define custom overloads
> for the standard operators. This way, you can write your expressions
> using notation much closer to the original maths.

Operator overloading is a controversial issue. Some like it, some don't.
Some think having it in a language makes it better, some think it makes
it worse. In any case, you can never write your expressions close to
mathematical notation in PostScript, so that's not a good reason to
prefer overloading. I don't think much would be gained if people could
multiply vectors using "mul" instead of "Vmul".

> 
> > assuming pix is a dictionary. Here is the start of a vector library:
> > 
> >    /Vector { 2 packedarray } bind def
> >    /x      { 0 get         } bind def
> >    /y      { 1 get         } bind def
> >    /xy     { aload pop     } bind def
> > 
> >    /Vop    { 3 1 roll
> >              xy 3 -1 roll xy
> >              3 -1 roll 4 index exec
> >              3 1 roll exch 3 index exec
> >              exch Vector
> >              exch pop      } bind def
> > 
> >    /Vdiv   { { div } Vop   } bind def  
> 
> Not much of a start, don’t you think
> <https://groups.google.com/d/msg/comp.lang.postscript/fEyXR90-wq4/AsOwYiltBgAJ>?

Just the necessary to translate to PostScript the snippets you are
posting.

> 
> > Again, a matter of libraries  
> 
> Which PostScript is, frankly, no help with.

It helps with the writing; coding in PostScript is enjoyable.

> > [Lexical binding is] a facility the Python compiler provides
> > because it's otherwise impossible to return custom functions. You
> > don't need the interpreter's help in PostScript, because procedures
> > are arrays, and you can easily create arrays programmatically. (By
> > the way, this is a recurring topic in this newsgroup lately.)  
> 
> But you cannot do the lexical binding. Not in a reentrant fashion.

Yes you can, but the interpreter won't do it automatically for you. I
just showed you! I don't know what you mean by "not in a reentrant
fashion"; if you found a case where it doesn't work please tell me.

Did you try it at all?

  GS>/add1 1 makeadder def  /add4 4 makeadder def
  GS>8 add1 add5 ==
  13


> > Try this:  
> 
> How many lines of PostScript code have you written so far? Compare it
> to how many lines of Python code I needed to write.

What? You wrote more lines. Or wasn't the code for Vector and Rectangle
classes written by you? I mean, line for line, PostScript wins hands
down. Compare:

    def __sub__(v1, v2) :
        "difference between two Vectors."
        return \
            (
                lambda : NotImplemented,
                lambda : type(v1)(v1.x - v2.x, v1.y - v2.y)
            )[isinstance(v2, Vector)]()
    #end __sub__

with

   /Vsub   { { sub } Vop   } bind def  % vector difference

> And your solution isn’t even complete yet.

Well, you didn't post a complete solution either, just some snippets
(the code in the original message also wasn't complete). If you want,
post a complete solution and I'll try to produce a PostScript
equivalent, so you can see Python isn't better :)

-- 

[toc] | [prev] | [next] | [standalone]


#2936

FromLawrence D’Oliveiro <lawrencedo99@gmail.com>
Date2016-11-14 15:15 -0800
Message-ID<8fc71ab3-e706-4f17-a7d6-c1d685577bf4@googlegroups.com>
In reply to#2925
On Wednesday, October 26, 2016 at 8:07:32 AM UTC+13, Carlos wrote:

> Operator overloading is a controversial issue.

No it isn’t. Even common-or-garden languages like C or Java have operator overloading.

Or did you mean *custom* operator overloads? It may be “controversial” the way C++ does it (complicated and clunky). But Python handles it in a very simple way.

> Just the necessary to translate to PostScript the snippets you are
> posting.

The Python code I included in that posting was not “snippets”, it was the complete program.

> What? You wrote more lines. Or wasn't the code for Vector and Rectangle
> classes written by you? I mean, line for line, PostScript wins hands
> down. Compare:
> 
>     def __sub__(v1, v2) :
>         "difference between two Vectors."
>         return \
>             (
>                 lambda : NotImplemented,
>                 lambda : type(v1)(v1.x - v2.x, v1.y - v2.y)
>             )[isinstance(v2, Vector)]()
>     #end __sub__
> 
> with
> 
>    /Vsub   { { sub } Vop   } bind def  % vector difference

Fine. If you want to include all that code, then by all means provide PostScript equivalents for all 6826 lines (current count) of my Cairo binding <https://github.com/ldo/qahirah>. Then we can compare.

How many lines of PostScript would that take? I predict you will not be able to do it all, no matter how many lines you write.

[toc] | [prev] | [next] | [standalone]


#2937

FromCarlos <angus@quovadis.com.ar>
Date2016-11-16 00:17 +0100
Message-ID<20161116001758.670c83db@samara.DOMA>
In reply to#2936
[Lawrence D’Oliveiro <lawrencedo99@gmail.com>, 2016-11-14 15:15]
> On Wednesday, October 26, 2016 at 8:07:32 AM UTC+13, Carlos wrote:
> 
> > Operator overloading is a controversial issue.  
> 
> No it isn’t. Even common-or-garden languages like C or Java have
> operator overloading.

Well, yes, even PostScript has it.

> Or did you mean *custom* operator overloads? It may be
> “controversial” the way C++ does it (complicated and clunky). But
> Python handles it in a very simple way.

That's what I meant. I think in a language like PostScript it's better
not to do it, for two main reasons: first (already mentioned), there is
no mathematical notation in PostScript; and second, operators provide
almost all of the code legibility, so the less ambiguous their names,
the better.

But what's great about PostScript is its flexibility. Almost any
language feature is just a library away. If you like operator
overloading, you can have it in PostScript!

Here's an example with a not very sophisticated library (~250 lines).
It's the same vector library stub as last time, but now overloading the
mul operator.

   /vectortype /packedarraytype {
       dup length 2 eq exch { /numbertype isa and } forall
   } deftype

   /Vector { 2 packedarray } bind def
   /x      { 0 get         } bind def
   /y      { 1 get         } bind def
   /xy     { aload pop     } bind def

   /Vop    { 3 1 roll
             xy 3 -1 roll xy
             3 -1 roll 4 index exec
             3 1 roll exch 3 index exec
             exch Vector
             exch pop      } bind def

   /Vmul   { { mul } Vop   } bind def

   /mul [/vectortype /vectortype] { Vmul } defmethod
   
   /mul [/vectortype /numbertype] {
       exch 2 copy x mul
       3 1 roll    y mul  Vector
   } defmethod


   GS>1.5 2 Vector   dup ==   dup type ==   dup dup mul ==   5 mul ==
   [1.5 2]
   vectortype
   [2.25 4]
   [7.5 10]

> > Just the necessary to translate to PostScript the snippets you are
> > posting.  
> 
> The Python code I included in that posting was not “snippets”, it was
> the complete program.

In _that_ posting there were just snippets. In the referred one, there
was some code interspersed with commentary. Are you saying the code
without the commentary make up a complete, working program? In that
case, I shall try to translate it to PostScript. Can I see what the
output is?

> > What? You wrote more lines. Or wasn't the code for Vector and
> > Rectangle classes written by you? I mean, line for line, PostScript
> > wins hands down. Compare:
> > 
> >     def __sub__(v1, v2) :
> >         "difference between two Vectors."
> >         return \
> >             (
> >                 lambda : NotImplemented,
> >                 lambda : type(v1)(v1.x - v2.x, v1.y - v2.y)
> >             )[isinstance(v2, Vector)]()
> >     #end __sub__
> > 
> > with
> > 
> >    /Vsub   { { sub } Vop   } bind def  % vector difference  
> 
> Fine. If you want to include all that code, then by all means provide
> PostScript equivalents for all 6826 lines (current count) of my Cairo
> binding <https://github.com/ldo/qahirah>. Then we can compare.

Actually, it was you who wanted to include my library code in the line
count, while excluding yours. We can count it or not, it's the same to
me. In any case, I'll only write the code needed for the task at hand;
if you want to include library code in the count, I don't expect you to
count your code not involved in the task.

> How many lines of PostScript would that take? I predict you will not
> be able to do it all, no matter how many lines you write.

That's an easy prediction; PostScript doesn't have facilities to load
or access DLLs. But that's not what this is about, is it? This is about
the *languages*, no the libraries.
-- 

[toc] | [prev] | [next] | [standalone]


#2948

FromCarlos <angus@quovadis.com.ar>
Date2016-11-21 18:37 +0100
Message-ID<o0vbbe$qi9$1@dont-email.me>
In reply to#2937
The purpose of this experiment is to demonstrate that there isn't a
lack of features in PostScript with respect to other programming or
scripting languages. On the contrary, the flexibility of PostScript
allows you to add features to the language, something not really
possible in many other languages.

As Markus said, PostScript is malleable. With it you can make a
program right away, or make bricks and parts to make it, or make tools
to help you to make parts.... etc. In many other languages you can
only use and combine the set of parts they come with.

In this particular case, if you like to work with closures and objects
that encapsulate vectors and rectangles, you can do it equally well in
Python as in PostScript. You can easily adapt PostScript to your
preferred way of coding.

The following is a line-for-line translation of the code in this
message:
https://groups.google.com/d/msg/comp.lang.postscript/fEyXR90-wq4/muGN64FvBgAJ

It's not idiomatic PostScript, and uses features maybe I wouldn't, but
the point is that in PostScript you *can*. When a PostScript
programmer rejects certain features or programming styles, it usually
isn't a case of sour grapes.

The support code (the "library") follows in the next message. To run
this, just do

   gs library-code.ps this-code.ps

or equivalent. There is no operator overloading here. I can post the
proto-libray if you want to play with it (it works, I just didn't want
to bother with it).

%!PS

/pix << /dimensions 400 400 Vector >> def

/reset {
     gsave
     .95 setgray
     0 0 pix /dimensions get xy rectfill
     grestore
     /Helvetica 12 selectfont
} bind def

/display {
     showpage
} bind def

/kernel << [ 1  3  6  9 12 15 18 20 23 25
             27 30 33 36 39 41 43 46 48 51
             54 57 60 63 66 68 71 73 75 78
             80 83 86 89 92 95 97 99 ] { true } forall
>> def

/weights [ -1 -1  1 -1  1  1 -1 -1  1  1
            -1  1 -1 -1  1 -1  1  1 -1  1
            -1 -1  1  1 -1 -1  1 -1  1  1
            -1 -1  1  1 -1  1 -1 -1  1  1
            -1 -1  1 -1  1  1 -1  1 -1 -1
             1 -1  1  1 -1 -1  1  1 -1  1
            -1 -1  1 -1  1  1 -1  1 -1 -1
             1  1 -1 -1  1 -1  1  1 -1  1
            -1 -1  1 -1  1  1 -1 -1  1  1
            -1  1 -1 -1  1  1 -1 -1  1 -1
] def

%: nodenr -> bool
/inkernel { kernel exch known } bind def

%: nodenr -> 1|-1
/weight { 1 sub weights exch get } bind def

%: drawnodeproc ->
/drawnodesgrid {
     reset
     6 dict begin
     /drawnode exch def
     /celldims  pix /dimensions get  10 10 Vector  Vdiv  def
     0 1 9 { /row exch def        % for
         0 1 9 { /col exch def      % for
             /nodenr row 10 mul  col add  1 add def
             /bounds 0 0 Vector  celldims  Rectfromcorners
                 celldims  col row Vector  Vmul
                 Radd
             def
             gsave
             bounds nodenr drawnode
             grestore
     } for
   } for
   end
   showpage
} bind def

%: inkernelcolour notkernelcolour posweightcolour negweightcolour -> drawnodeproc
/makedrawnode1 {
     6 dict begin
     /negweightcolour exch def  /posweightcolour exch def
     /notkernelcolour exch def  /inkernelcolour  exch def
     %: bounds nr ->
     {
         5 dict begin
         /nr exch def  /bounds exch def
         /fillcolour  nr inkernel { inkernelcolour } { notkernelcolour } ifelse def
         /bordercolour << -1 negweightcolour  1 posweightcolour >>  nr weight  get def
         fillcolour setcolorp
         newpath
         bounds Rfill
         bordercolour setcolorp
         3 setlinewidth
         bounds  1.5 1.5 Vector Rinset  Rstroke

         /label nr  10  5 string  cvrs def
         /extents  label stringextents def

         bounds Rmiddle  extents width 2 div neg  extents height 2 div neg Vector  Vadd
           aload pop  moveto

         label show
         end
     } bindcurrent
     end
} bind def

/exampledrawnode
     0.5 0.5 0.9  SolidPattern  ColorfromHSBP
     0   0   0    EmptyPattern  ColorfromHSBP
     0   0   0    SolidPattern  ColorfromHSBP
     0   0   0.5  SolidPattern  ColorfromHSBP
     makedrawnode1
def

/exampledrawnode load drawnodesgrid

-- 

[toc] | [prev] | [next] | [standalone]


#2949

FromCarlos <angus@quovadis.com.ar>
Date2016-11-21 18:39 +0100
Message-ID<o0vbfc$qi9$2@dont-email.me>
In reply to#2948
On 21/11/2016 18:37, Carlos wrote:
> The support code (the "library") follows in the next message.

Here it is:

%!PS

% PART 0 - min & max

/min    { 2 copy gt { exch } if pop } bind def
/max    { 2 copy lt { exch } if pop } bind def

% PART 1 - Geometric things

% vector: 2 numbers (x y) in an array

%: x y -> vector
/Vector { 2 packedarray } bind def

/x      { 0 get         } bind def
/y      { 1 get         } bind def
/xy     { dup x exch y  } bind def

%: x1 y1 x2 y2 -> vector1 vector2
/2Vectors {
     Vector
     3 1 roll  Vector
     exch
} bind def

% applies op to corresponding components
% v1 v2 op ==
%  v1 x v2 x op  v1 y v2 y op  Vector

%: v1 v2 op -> vector
/Vop    { 3 1 roll
           xy 3 -1 roll xy
           3 -1 roll 4 index exec
           3 1 roll exch 3 index exec
           exch Vector
           exch pop      } bind def

% vector operators. all signatures are
%: vector vector op -> vector

/Vdiv   { { div } Vop   } bind def
/Vmul   { { mul } Vop   } bind def
/Vadd   { { add } Vop   } bind def
/Vsub   { { sub } Vop   } bind def

% scalar mul and div
%: vector n -> vector
/Vsmul  { dup Vector Vmul } bind def
/Vsdiv  { dup Vector Vdiv } bind def

% rectangle: (x y width height)

%: x y width height -> Rect
/Rect   { 4 packedarray } bind def

%: x1 y1 x2 y2 -> rect
/Rectfromcorners {
     2 copy { min } Vop
     3 1 roll { max } Vop
     1 index Vsub
     exch xy 3 -1 roll xy
     Rect
} bind def


/width  { 2 get } bind def
/height { 3 get } bind def

%: rect -> width height
/w+h    { dup width exch height } bind def

% center point
%: rect -> vector
/Rmiddle { dup xy Vector  exch w+h Vector 2 Vsdiv  Vadd } bind def

% make rect a little smaller
%: rect vector -> rect
/Rinset {
     2 copy exch xy Vector Vadd
     3 1 roll
     2 Vsmul exch w+h Vector exch Vsub
     exch aload pop 3 -1 roll aload pop
     Rect
} bind def

% move rect
%: rect vector -> rect
/Radd {
     1 index x  2 index y Vector Vadd xy
     3 -1 roll w+h Rect
} bind def

% fill and stroke
%: rect ->

/Rfill   { aload pop rectfill   } bind def
/Rstroke { aload pop rectstroke } bind def


% PART 3 - Colors

/SolidPattern <<
     /PatternType 1
     /PaintProc { pop 0 0 10 10 rectfill }
     /BBox [ 0 0 10 10 ]  /XStep 5  /YStep 5
     /PaintType 2  /TilingType 1
>> matrix makepattern def

/EmptyPattern <<
     /PatternType 1
     /PaintProc { pop }
     /BBox [ 0 0 10 10 ]  /XStep 5  /YStep 5
     /PaintType 2  /TilingType 1
>> matrix makepattern def

/ColorfromHSBP {
     4 1 roll  gsave sethsbcolor currentrgbcolor grestore
     4 -1 roll 4 array astore
} bind def

/setcolorp {
     [ /Pattern [ /DeviceRGB ] ] setcolorspace
     aload pop setcolor
} bind def

% PART 4 - extents

%: string -> extents
/stringextents {
     gsave
     newpath 0 0 moveto
     true charpath pathbbox 2Vectors Rectfromcorners
     currentpoint exch pop  1 index y  sub  % depth
     exch w+h  2 index sub  3 -1 roll       % width height depth
     0 0 5 2 roll 5 packedarray
     grestore
} bind def

/depth { 4 get } bind def


% PART 5 - bindcurrent and helpers

% copies array recursively
% <array> -> <new array>
/deepcopy {
     dup xcheck exch
     dup length array copy
     dup length 1 sub 0 exch 1 exch { % for       % a i
         2 copy 2 copy get dup type
         dup /arraytype eq exch /packedarraytype eq or % a i a i e ?
         { % ifelse
             deepcopy put
         }
         {
             pop pop pop
         } ifelse
         pop
     } for
     exch { cvx } if
} bind def

% recursively replaces elements in <array> found in <dict>
% <array> <dict> -> -
/replaceall {
     1 index length 1 sub  0 1  3 -1 roll { % for 0 1 length-1
         3 copy  3 -1 roll  exch    % a d i d a i
         get                        % a d i d e
         2 copy known               % a d i d e ?
         % ifelse
         {                          % a d i d e
             get                    % a d i v
             3 index  3 1 roll      % a d a i v
             put
         } % else
         {                          % a d i d e
             dup type /arraytype eq % a d i d e ?
             { exch replaceall }
             { pop pop } ifelse
             pop
         } ifelse                   % a d
     } for
     pop pop
} bind def

% bind names existing in currentdict
% proc -> proc
/bindcurrent {
     deepcopy dup currentdict replaceall
} bind def

-- 

[toc] | [prev] | [next] | [standalone]


#2924

FromMarkus Triska <triska@metalevel.at>
Date2016-10-25 20:52 +0200
Message-ID<m2h980dzwr.fsf@metalevel.at>
In reply to#2921
Lawrence D’Oliveiro <lawrencedo99@gmail.com> writes:

> Would anybody like to try doing this in PostScript? It would take at
> least twice as much work.

The way I approached the task in PostScript was to first think about how
I would eventually like to describe the layout within PostScript.

Then, I added the necessary definitions so that I could describe the
whole graph (100 nodes) like this:

    /instrs {
        {r r r r r r r r r r r r r r r r
                                          d
             l l l l l l l l l l l l l l
           d
             r r r r r r r r r r r r r r r
                                           d
               l l l l l l l l l l l l l l
              d
               r r r r r r r r r r r r r
                                         d
         l l l l l l l l l l l l l l l l
         u r u l u u u } } def

You can download the whole source from:

    https://www.metalevel.at/postscript/cyclegraph.ps

It's about 80 lines of PostScript. This general approach has served me
very well also for other graphs, and makes it easy to try variations
using only your keyboard and editing facilities of Emacs.

> And it still wouldn’t be interactive.

That's true, it is not interactive.

When I program in PostScript, it feels a bit like handling plasticine:
It is very simple and uniform, and you can mold it quite freely. When I
see your Python code, it feels a bit like playing with an action figure:
I understand it can be appealing to some, and it may feature a few cool
gizmos, but it feels more rigid and inflexible, and less uniform.

All the best,
Markus

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.postscript


csiph-web