开发者

Postscript: Drawing a Gradient

开发者 https://www.devze.com 2023-04-06 15:43 出处:网络
I\'m learning Postscript I\'m trying to create a method for that would draw a vertical gradient. Here is my code:

I'm learning Postscript I'm trying to create a method for that would draw a vertical gradient.

Here is my code:

%!PS-Adobe-3.0

%%%%%%%%%%%%%%%%%%%%%%%
% draw a RECTANGLE
/Rect {
/h exch def % height
/w exch def % width
w 0 rlineto
0 h rlineto
-1.0 w mul  0 rlineto
0 -1.0 h mul rlineto
} def
%%%%%%%%%%%%%%%%%%%%%%%
% draw a Gradient
/VGrad {
/h exch def % height
/w exch def % width
/c2 exch def %gray-end
/c1 exch def %gray-start
/index 0.0  def %loop-index

0 1 h { %loop over height
    gsave
    c2 c1 sub  index h div mul c1 add setgray

    w h index sub Rect
    stroke

    /index index 1.0 add def % index++
    grestore
    } for

} def
%%%%%%%%%%%%%%%%%%%%%%%
%test script
200 600 moveto
.1 .9 100 10 VGrad

showpage

But GS raises an error:

GPL Ghostscript 8.70 (2009-07-31)
Copyright (C) 2009 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Error: /undefinedresult in --div--
Operand stack:
   0   1   2   3   4   5   0.8   5.0   0.0
Execution stack:
   %interp_exit   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   --nostringval--   --nostringval--   false   1   %stopped_push   1862   1   3   %oparray_pop   1861   开发者_StackOverflow中文版1   3   %oparray_pop   1845   1   3   %oparray_pop   1739   1   3   %oparray_pop   --nostringval--   %errorexec_pop   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   6   1   10   --nostringval--   %for_pos_int_continue   --nostringval--
Dictionary stack:
   --dict:1150/1684(ro)(G)--   --dict:0/20(G)--   --dict:75/200(L)--
Current allocation mode is local
Current file position is 588
GPL Ghostscript GPL Ghostscript 8.708.70: : Unrecoverable error, exit code 1
Unrecoverable error, exit code 1

where am I wrong ?


Your program will execute faster by using clever stack manipulation and CTM effects.

This is not a smooth gradient like yours, but executes much faster, and the functions are computed as one-line statements (which I just like better, can't explain why).

Also it's nice to post with usage and maybe a sample page (easy to trim when you don't need it, but when you do need it...??!!) Anyway, here's your program rewritten my way, FWIW.

As I said, the output it not as pretty in its current form. But you can modify the gradient by changing the gray-transfer function using currenttransfer and settransfer and/or change the calculation of the boxes to a logorithmic scaling, change the range and velocity of the grays. These things should be easier to see in "tighter" code. The stack comments help you to "check your understanding" at the end of each line.

Edit: I couldn't stop playing with it! I've factored out the loop and teased out some more parameters.

Edit: One more expansion. And how about a pretty picture?

%!

/box { % x y w h
    4 2 roll moveto % w h
    1 index 0 rlineto % w h
    0 exch rlineto % w
    neg 0 rlineto %
    closepath
} def

/poly { % n
    0.5 0 moveto
    { ? rotate 0.5 0 lineto } % n proc
    dup 0 360 4 index div put % n {360/n...}
    repeat
    closepath
} def

% num-slices shapeproc matrix grayproc  agrad  -
% repeatedly (fill shape, concat matrix, transform currentgray)
/agrad {
    3 dict begin /gray exch def /mat exch def /shape exch def
    ({ //shape exec //mat concat currentgray //gray exec setgray })
    token pop exch pop end bind repeat
} def

/shapes [
    { -0.5 -0.5 1 1 box fill }   %box shape
    { 0 0 0.5 0 360 arc fill }   %circle shape
    { 0 0 0.5 0 180 arc fill }   %fan shape
    { 5 poly fill } %pentagon
    { 6 poly fill } %hexagon
    ] def

/mats [
    {1 index 2 exch div 1 exch sub   dup matrix scale } %pyramid matrix
    {1 index 2 exch div 1 exch sub   1 matrix scale } %horizontal matrix
    {1 index 2 exch div 1 exch sub   1 exch matrix scale } %vertical matrix
    ] def

% mat-no shape-no gray0 grayF n x y w h  dograd  -
/dograd {
    gsave
        4 2 roll translate % m sh g0 gF n w h
        scale % m sh g0 gF n
        3 1 roll % m sh n g0 gF
        1 index sub 2 index div % m sh n g0 (gF-g0)/n
        [ exch /add cvx ] cvx % m sh n g0 grayproc
        3 1 roll setgray % m sh grayproc n
        3 -1 roll shapes exch get % m gray n shape
        4 -1 roll mats exch get exec % gray n shape mat
        4 -1 roll %n shape matrix gray
        agrad
    grestore
} def

%mat shape g0 gF n x y w h
0 4 .7 .1 20 300 400 600 800 dograd

0 0 0 1 10 100 650 200 200 dograd
1 1 0 1 20 300 650 200 200 dograd
2 2 .5 1 30 500 650 200 200 dograd

0 3 1 0 40 100 400 200 200 dograd
1 4 1 .5 50 300 400 200 200 dograd
2 1 .5 0 60 500 400 200 200 dograd

0 2 .1 .9 10 100 150 200 200 dograd
1 3 .2 .8 20 300 150 200 200 dograd
2 4 .3 .7 30 500 150 200 200 dograd

showpage

Postscript: Drawing a Gradient


Ok, I found the problem: It seems that index is a reserved word. Here is a functional version:

/box
{
4 dict begin
/height exch def
/width exch def
/y exch def
/x exch def
x y moveto
width 0 rlineto
0 height rlineto
width -1 mul 0 rlineto
0 height -1 mul rlineto
end
} bind def


/gradient
{
4 dict begin
/height exch def
/width exch def
/y exch def
/x exch def
/i 0 def
height 2 div /i exch def

0 1 height 2 div {
    1 i height 2.0 div div sub setgray
    newpath
    x  
    y height 2 div i sub  add
    width
    i 2 mul
    box
    closepath
    fill
    i 1 sub /i exch def
    }for
newpath
0 setgray
0.4 setlinewidth
x y width height box
closepath
stroke
end
} bind def


I didn't try to understand your code fully. But the error message tries to tell you that you are dividing by zero (look at the top element of the remaining operand stack: "0").

Just by adding "1" to your h variable (insert 1 add after h) makes your PostScript program run through the Ghostscript interpreter and let it draw something (though that may not look like you envisaged....).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号