JaMImagerDoc.tioga
Tim Diebert: February 24, 1986 10:56:17 am PST
Michael Plass, March 13, 1986 3:42:24 pm PST
Rick Beach, January 18, 1986 12:05:14 pm PST
Last edited by: Mik Lamming - November 10, 1987 11:21:32 am PST
Maureen Stone, July 10, 1987 1:36:40 pm PDT
Bier, September 15, 1992 6:06 pm PDT
JaM Imager
CEDAR 6.0 —
JaM Imager
Tim Diebert
© Copyright 1985 Xerox Corporation. All rights reserved.
Abstract: JaMImager augments the JaM language with a set of primitives that invoke Imager commands. In addition, it creates a window in which the results of these commands are displayed. As augmented by JaMImager, JaM is similar in many respects to the PostScriptTM language.
Created by: Tim Diebert & friends
Maintained by: Tim Diebert <Diebert.pa>
Keywords: JaM, Imager
XEROX  Xerox Corporation
   Palo Alto Research Center
   3333 Coyote Hill Road
   Palo Alto, California 94304

1. Commands from the Package
Notation
op <arg1> <arg2> b <> õ Description.
means the command op takes the two arguments <arg1> <arg2> from the stack, and replaces them with (in this case) nothing. <arg2> is nearest the top of the stack.
<VEC> is a pair of real numbers on the stack, <x> <y>
<RECTANGLE> is four reals, <x> <y> <w> <h>
<BODY> is executable JaM code, i.e., {1 2 3 4 .maskrectangle} .cvx
Commands implemented by JaMImagerImpl
.dosave <BODY> b <> õ Execute <BODY> under a DoSave imager op.
.dosaveall <BODY> b <> õ Execute <BODY> under a DoSaveAll imager op.
.dround <VEC> b <VEC> õ Performs ImagerTransformation.DRound.
.maket <a> <b> <c> <d> <e> <f> b <ImagerTransformation.Transformation> õ Performs ImagerTransformation.Create
.opent <ImagerTransformation.Transformation> b <a> <b> <c> <d> <e> <f> õ Performs ImagerTransformation.Open
.translate <VEC> b <ImagerTransformation.Transformation> õ Performs ImagerTransformation.Translate
.rotate <r> b <ImagerTransformation.Transformation> õ Performs ImagerTransformation.Rotate
.scale <r> b <ImagerTransformation.Transformation> õ Performs ImagerTransformation.Scale
.scale2 <x> <y> b <ImagerTransformation.Transformation> õ Performs ImagerTransformation.Scale2
.concat <ImagerTransformation.Transformation 1> <ImagerTransformation.Transformation 2> b <ImagerTransformation.Transformation> õ Performs ImagerTransformation.Concat[t2, t1]
.invert <ImagerTransformation.Transformation> b <ImagerTransformation.Transformation> õ Performs ImagerTransformation.Invert
.transform <VEC> <ImagerTransformation.Transformation> b <VEC> õ Performs ImagerTransformation.Transform[t, vec]
.transformvec <VEC> <ImagerTransformation.Transformation> b <VEC> õ Performs ImagerTransformation.TransformVec[t, vec]
.roundxy <VEC> <ImagerTransformation.Transformation> b <VEC> õ Performs ImagerTransformation.RoundXY
.roundxyvec <VEC> <ImagerTransformation.Transformation> b <VEC> õ Performs ImagerTransformation.RoundXYVec
.concatt <ImagerTransformation.Transformation> b <> õ Performs Imager.ConcatT
.scalet <r> b <> õ Performs Imager.ScaleT
.scale2t <VEC> b <> õ Performs Imager.Scale2T
.rotatet <r> b <> õ Performs Imager.RotateT
.translatet <VEC> b <> õ Performs Imager.TranslateT
.moveõ Performs Imager.Move
.transõ Performs Imager.Trans
.setxy <VEC> b <> õ Performs Imager.SetXY
.setxyrel <VEC> b <> õ Performs Imager.SetXYRel
.setxrel <x> b <> õ Performs Imager.SetXRel
.setyrel <y> b <> õ Performs Imager.SetYRel
.getcp <> b <VEC> õ Performs ImagerBackdoor.GetCP (rounded FALSE)
.getcprounded <> b <VEC> õ Performs ImagerBackdoor.GetCP (rounded TRUE)
.findfont <(fontname)> b <ImagerFont.Font> õ Performs ImagerFont.Find
.modifyfont <ImagerFont.Font> <ImagerTransformation.Transformation> b <ImagerFont.Font> õ Performs ImagerFont.Modify
.scalefont <ImagerFont.Font> <s> b <ImagerFont.Font> õ Performs ImagerFont.Scale
.setfont <ImagerFont.Font> b <> õ Performs Imager.SetFont
.fontbox <> b <ImagerFont.Extents> õ ImagerFont.ImagerFont.FontBoundingBox of the current font
.textbox <(rope)> b <ImagerFont.Extents> õ ImagerFont.RopeBoundingBox of the current font
.setamplifyspace <r> b <> õ Performs Imager.SetAmplifySpace
.showrope <(rope)> b <> õ Performs Imager.ShowRope
.showxchar <set> <code> b <> õ Performs Imager.ShowXChar
.startunderlineõ Performs Imager.StartUnderline
.maskunderline <dy> <h> b <> õ Performs Imager.MaskUnderline
.correctmaskõ Performs Imager.CorrectMask
.correctspace <VEC> b <> õ Performs Imager.CorrectSpace
.space <r> b <> õ Performs Imager.Space
.amplifiedspace <x> b <> õ Imager.Space[context, x*amplifySpace];
.setcorrectmeasure <VEC> b <> õ Imager.SetCorrectMeasure
.setcorrecttolerance <VEC> b <> õ Imager.SetCorrectTolerance
.setcorrectshrink <r> b <> õ Imager.SetCorrectShrink
.correct <executable code> b <> õ Imager.Correct
.dontcorrect <executable code> <saveCP (BOOL)> b <> õ Imager.DontCorrect[context, action, saveCP]
.setcolor <ImagerColor.Color> b <> õ Imager.SetColor
.makegray <r> b <ImagerColor.Color> õ Imager.MakeGray
.setgray <r> b <> õ Imager.SetGray
.graylinearcolormodel <> b <ImagerColorOperator.ColorOperator> õ ImagerColorOperator.GrayLinearColorModel
.rgblinearcolormodel <> b <ImagerColorOperator.ColorOperator> õ ImagerColorOperator.RGBLinearColorModel
.pixelarrayfromais <(name)> b <ImagerPixelArray.PixelArray> õ ImagerPixelArray.FromAIS
.pixelarrayfrom3ais <red> <blue> <green> b <ImagerPixelArray.PixelArray> õ ImagerPixelArray.Join3AIS
.pixelarraybounds <ImagerPixelArray.PixelArray> b <RECTANGLE> õ
.pixelarraysamplesperpixel <ImagerPixelArray.PixelArray> b <samplesperpixel> õ
.pixelarray
.makesampledcolor <ImagerPixelArray.PixelArray> <ImagerTransformation.Transformation> <ImagerColorOperator.ColorOperator> b <ImagerColor.Color> õ ImagerColor.MakeSampledColor
.makesampledblack <clear (BOOL)> <ImagerPixelArray.PixelArray> <ImagerTransformation.Transformation> b <ImagerColor.Color> õ ImagerColor.MakeSampledBlack
.setsampledcolor <ImagerPixelArray.PixelArray> <ImagerTransformation.Transformation> <ImagerColorOperator.ColorOperator> b <> õ ImagerColor.SetSampledColor
.setsampledblack <ImagerPixelArray.PixelArray> <ImagerTransformation.Transformation> <clear (BOOL)> b <> õ ImagerColor.SetSampledBlack
.lastpoint <ImagerPath.Trajectory> b <VEC> õ ImagerPath.LastPoint
.moveto <VEC> b <ImagerPath.Trajectory> õ ImagerPath.MoveTo
.lineto <ImagerPath.Trajectory> <VEC> b <ImagerPath.Trajectory> õ ImagerPath.LineTo
.linetox <ImagerPath.Trajectory> <x> b <ImagerPath.Trajectory> õ ImagerPath.LineToX
.linetoy <ImagerPath.Trajectory> <y> b <ImagerPath.Trajectory> õ ImagerPath.LineToY
.curveto <ImagerPath.Trajectory> <VEC1> <VEC2> <VEC3> b <ImagerPath.Trajectory> õ ImagerPath.CurveTo
.conicto <ImagerPath.Trajectory> <VEC1> <VEC2> <r> b <ImagerPath.Trajectory> õ ImagerPath.ConicTo
.arcto <ImagerPath.Trajectory> <VEC1> <VEC2> b <ImagerPath.Trajectory> õ ImagerPath.ArcTo
.makeoutline <ImagerPath.Trajectoryi> <ImagerPath.Trajectoryi-1> ... <ImagerPath.Trajectorycnt> <cnt (INT)> b <ImagerPath.Outline> õ Creates an outline
.maskfill <ImagerPath.Outline> b <> õ Imager.MaskFillOutline (parity FALSE)
.maskfillparity <ImagerPath.Outline> b <> õ Imager.MaskFillOutline (parity TRUE)
.maskfilltrajectory <ImagerPath.Trajectory> b <> õ Imager.MaskFillTrajectory (parity FALSE)
.maskfilltrajectoryparity <ImagerPath.Trajectory> b <> õ Imager.MaskFillTrajectory (parity TRUE)
.setstrokewidth <r> b <> õ Imager.SetStrokeWidth
.setstrokeend <i> b <> õ Sets stroke end. Defs in JaMImager.jam
.setstrokejoint <i> b <> õ Sets stroke joint. Defs in JaMImager.jam
.maskstroke <ImagerPath.Trajectory> b <> õ Imager.MaskStrokeTrajectory
.maskstrokeclosed <ImagerPath.Trajectory> b <> õ Imager.MaskStrokeTrajectory (closed TRUE)
.maskdashedstroke <ImagerPath.Trajectory> <pattern: ARRAY OF REAL> <offset: REAL> <length: REAL> b <> õ makes a dashed stroke
Makes a dashed stroke along the trajectory. The elements of pattern are used cyclically to specify the arc lengths of the strkes and spaces. The offset allows the dashing to start part of the way into the pattern. The length provides the client's estimate of the arc length, so that the dashes will end in a predictable way; if it is zero, the actual arc length of the trajectory is used.
.maskrectangle <RECTANGLE> b <> õ Imager.MaskRectangle
.maskbox <xmin> <ymin> <xmax> <ymax> b <> õ Imager.MaskBox
.maskvector <VEC1> <VEC2> b <> õ Imager.MaskVector
.maskpixel <ImagerPixelArray.PixelArray> b <> õ Imager.MaskPixel
.setpriorityimportant <BOOL> b <> õ Imager.SetPriorityImportant
.setnoimage <BOOL> b <> õ Imager.SetNoImage
.clipoutline <ImagerPath.Outline> b <> õ Imager.ClipOutline (exclude FALSE)
.excludeoutline <ImagerPath.Outline> b <> õ Imager.ClipOutline (exclude TRUE)
.cliprectangle <RECTANGLE> b <> õ Imager.ClipRectangle (exclude FALSE)
.excluderectangle <RECTANGLE> b <> õ Imager.ClipRectangle (exclude TRUE)
Commands implemented by JaMIColorImpl
.turnoncolor <bits> b <> õ Starts the color display in bits per pixel
.turnoffcolorõ Stops the color display.
.onleft <BOOL> b <> õ If true the display goes on the left
.colorfromname <ROPE> b <ImagerColor.Color> õ NamedColors.RopeToHSL
.red <> b <ImagerColor.Color> õ colorfromname "Vivid Red"
.green <> b <ImagerColor.Color> õ colorfromname "Vivid Green"
.blue <> b <ImagerColor.Color> õ colorfromname "Vivid Blue"
.magenta <> b <ImagerColor.Color> õ colorfromname "Vivid Magenta"
.cyan <> b <ImagerColor.Color> õ colorfromname "Vivid Cyan"
.yellow <> b <ImagerColor.Color> õ colorfromname "Vivid Yellow"
.black <> b <ImagerColor.Color> õ colorfromname "Black"
.white <> b <ImagerColor.Color> õ colorfromname "White"
.findcolor <ROPE> b <ImagerColor.Color> õ ImagerColor.Find
.gray <> b <ImagerColor.Color> õ 50% gray
.icolor <r> b <ImagerColor.Color> õ r% gray
.rgbcolor <r> <g> <b> b <ImagerColor.Color> õ ImagerColor.ColorFromRGB
.hsvcolor <h> <s> <v> b <ImagerColor.Color> õ HSV Color
.hslcolor <h> <s> <l> b <ImagerColor.Color> õ HSL Color
.cmycolor <c> <m> <y> b <ImagerColor.Color> õ CMY Color
.cmykcolor <c> <m> <y> <k> b <ImagerColor.Color> õ CMYK Color
.hsvfromcolor <ImagerColor.Color> b <h> <s> <v> õ HSV from Color
.rgbfromcolor <ImagerColor.Color> b <r> <g> <b> õ RGB from Color
.hslfromcolor <ImagerColor.Color> b <h> <s> <l> õ HSL from Color
.rgbforvtec <r> <g> <b> b <r> <g> <b> õ See the code.
.blackcursorõ Sets black cursor
.whitecursorõ Sets white cursor
.mixRGB <r1> <g1> <b1> <r2> <g2> <b2> <%1> <%2> b <ImagerColor.Color> õ mixes (vector addition) two RGB colors based on the percentages supplied. Note that not all colors will be inside the RGB gamut. These are clipped to stay within range.
.mixHSL, .mixHSV, .mixCMY õ same as mixRGB except for these three systems.
.interpRGB <r1> <g1> <b1> <r2> <g2> <b2> <%d from 1 to 2> b <ImagerColor.Color> õ linearly interpolates between two rgb values. These are straight lines thru the color solid.
.interpHSL, .interpHSV, .interpCMY õ same as interpRGB except for these three systems.
Commands implemented by JaMIVector2Impl
.v2add <VEC1> <VEC2> b <VEC> õ Vector2.Add
.v2sub <VEC1> <VEC2> b <VEC> õ Vector2.Sub
.v2neg <VEC> b <VEC> õ Vector2.Neg
.v2mul <r> <VEC> b <VEC> õ Vector2.Mul
.v2div <r> <VEC> b <VEC> õ Vector2.Dev
.v2mulc <VEC1> <VEC2> b <VEC> õ Vector2.MulC
.v2divc <VEC1> <VEC2> b <VEC> õ Vector2.DivC
.v2dot <VEC1> <VEC2> b <VEC> õ Vector2.Dot
.v2cross <VEC1> <VEC2> b <VEC> õ Vector2.Cross
.v2square <VEC> b <r> õ Vector2.Square
.v2length <VEC> b <r> õ Vector2.Length
.v2unit <VEC> b <VEC> õ Vector2.Unit
.v2exch <VEC1> <VEC2> b <VEC2> <VEC1> õ Exchange the top vectors
Commands implemented by JaMIInterpressImpl
.writeinterpress (ip file name) [ <dcl0> <dcl1> . . . ] <BODY> b <>
Makes an Interpress master by executing <BODY>. The items in square braces are things to put in the preamble, i.e., fonts and pixelarrays. When <BODY> is executed, the page number is on the top of the stack; it should leave a value on the stack that is nonzero (e.g, .true) if it is the last page of the document, or zero (.false) if it wishes to do more pages; note that if <BODY> leaves that stack as it finds it, a one-page master will be created.
Example:
(Roman10) (Xerox/Pressfonts/TimesRoman-mrr) .findfont 10 .scalefont .def
(monkPixelArray) ([cyan]<AIS>monk.ais) .pixelarrayfromais .def
(foo) {
monkPixelArray .drawpa
1 .setgray 10 10 .setxy Roman10 .setfont
"Monk" .showrope
}.cvx .def
(print){(Foo.ip) [ Roman10 monkPixelArray ] {foo}.cvx .writeinterpress}.cvx .def
Multi-page example:
(bigfont) (xerox/pressfonts/timesroman-bir) .findfont 800 .scale .modifyfont .def
(count.ip) [ bigfont ] {
.dup = % Print the page number
bigfont .setfont% a one-char-per-page size font
72 72 .setxy% position for start of text
.dup .cvs% get page number as rope, but leave original on stack for later
.showrope% Show the big number
9 .eq% quit if this was page 9 (would like to say 9 .ge)
}.cvx .writeinterpress
.writeinterpresspages (ip file name) [ <dcl0> <dcl1> . . . ] [ <b0> <b1> . . . ] b <>
Makes an Interpress master by executing <b0> <b1> . . ., each for a separate page.
Implemented in JaMImager.JaM using .writeinterpress
Example:
(bigfont) (xerox/pressfonts/timesroman-bir) .findfont 700 .scale .modifyfont .def
(sho) {bigfont .setfont 0 72 .setxy .showrope} .cvx .def
(biglet.ip) [ bigfont ] [ {(B) sho} {(I) sho} {(G) sho} ] .writeinterpresspages
.makeinterpress <BODY> <(ip file name)> b <> õ For compatibility
Commands implemented by JaMIShowIPImpl
.showip <pageNo> (<ip file name>) b <>
Displays page <pageNo> of the interpress file <ip file name>. Page numbers start at 1.
Commands implemented by JaMRESImpl
.loadres (<res file name>) b <RES>
loads an RES file and returns descriptor.
.resbounds <RES> b <width> <height>
returns size of RES previously loaded using .loadres
For details on the following see ImagerRES.mesa
.showres <RES> <BOOL> b <>
displays a RES previously loaded using .loadres.
if BOOL then
res.imageScale will be used as a scale factor, assuming the client unit is meters
else
Scale is 1 RES-pixel per client unit
.showunitres <RES> <BOOL> b <>
Displays a RES file into the context provided. RES is scaled to just fit inside a client-unit sized box.
If BOOL the RES images is centered on 0,0 otherwise bottom left RES pixel is positioned at bottom left of box.
.setcolorres <RES> b <>
Equivalent to SetSampledColor using the colorImage and colorOperator components of res; if either is NIL, sets the color to black instead. Scale is 1 RES-pixel per client unit.
.setsampledblackres <RES> <BOOL> b <>
Equivalent to SetSampledBlack using the maskImage component of res; if maskImage is NIL, sets the color to black instead. Scale is 1 RES-pixel per client unit. If BOOL then 0 bits are clear.
.maskres <RES> b <>
Does a MaskPixel using the maskImage component of the res, ignoring colorImage and colorOperator. Scale is 1 RES-pixel per client unit. If maskImage is not present, does a MaskRectangle.
.combinealphaandmask <RES> b <pa>
Returns a 1 bit/sample (stipple) mask representing the transparency at each pixel of the RES (as determined from alpha channels and maskImage). May return NIL if everywhere is fully opaque.
Commands implemented by JaMIDunnIPImpl
.buildframe <BODY> b <pa>
Creates a colordisplay sized pixelarray and executes body. During the execution of body, imaging operations are directed at the pixelarray.
.snapframe <CARD> <pa> b <>
<CARD> copies of pixelarray are snapped by the Dunn camera. This operation only works on Reprisal. On other machines it is simulated.
.dunnsnap <CARD> <BODY> b <>
<CARD> <BODY> .dunnsnap is equivalent to <CARD> <BODY> .buildframe .snapframe
This is implemented by JaMImager.JaM
This is a package implementing four new JamM commands so that you can output images produced with JamImager to the Dunn camera. If you want to know more about the Dunn camera read the documentation for the Dunn command by Bloomenthall.
You can use the JaMIDunn package at any Cedar workstation that has a color display. For best results the display should be set in high-res mode (See ColorDisplayTool for details). However only REPRISAL is actually connected to the Dunn so if you want to really make pictures you have to run this package there. At other workstations JaMIDunn just fiddles with the color display.
When you take a picture on the Dunn the following events happen:
1) Reprisal makes a PUP connection to the Dicentra YORK which drives the Dunn
2) The current color display contents and color map are saved
3) The color display map is set to be a linear RED ramp
4) The red separation of your image is painted on the display
5) The red filter is positioned in front of the Dunn camera lens
6) An exposure is made - the film is not advanced!
7) Steps 3,4,5 and 6 are repeated for GREEN and BLUE
8) The shutter is closed and the film is advanced
9) Reprisal breaks the connection with YORK
WARNING: If you have a procedure that makes a lot of calls to ".dunnsnap" then Cedar may decide to go idle and blank the screen. In this case you get a whole heap of blank images. Temporary fix: Alter your user profile entry to: Viewers.AutoIdleTimeout: 0
Example
(displayProc) { % Draws three large "XEROX"'s
(xerox/pressfonts/helvetica-brr) 200 0 .nsrsetfont
100 500 .setxy .red .setcolor (XEROX) .show
100 300 .setxy .green .setcolor (XEROX) .show
100 100 .setxy .blue .setcolor (XEROX) .show
} .cvx .def
2 { displayProc } .cvx .dunnsnap % Take two snaps of picture
2. Examples and hints
The following examples use "sugar" defined in JaMImager.JaM
Gray scale and Color images
(mandrillPixelArray)
([cyan]<AIS>Baboon-red.ais) ([cyan]<AIS>Baboon-green.ais) ([cyan]<AIS>Baboon-blue.ais) .pixelarrayfrom3ais
.def
This makes a pixel array from the three named files, and saves it under the name "mandrillPixelArray". Note the lack of any brackets around part before the .def. You want to do this once, since it will allow the imager to work better if you use the same pixelarray each time, rather than going back out to the files. Making a pixel array does not require the whole AIS file to be read, so this is a relatively cheap operation, once the files are on your disk.
(monkPixelArray) ([cyan]<AIS>monk.ais) .pixelarrayfromais .def
This is a black-and-white image.
mandrillPixelArray .drawpa
draws one instance of the pixelarray, guessing that it is a color image from the fact that there are 3 samples per pixel. The first time you use a pixelarray as a color on a given device, there will be a pause while the image is read in and put into the right format for that device. Subsequent uses will be faster.
mandrillPixelArray .drawunitpa
same as above but it scales the image to fit inside a 1 pixel square box
mandrillPixelArray .setpacolor .printtouch .printtouch .drawbox
Takes two mouse clicks (printing the coordinates for later use) and fills their bounding box with mandrills.
Paths as arrays of trajectories
.red .setcolor .printtouch .printmoveto {.printtouch .printlineto .dup .maskstroke}.cvx .loop
This is a way to capture a polygon from a series of mouse clicks. Note the feedback is done in an inefficient way, drawing the whole stroke each time, but people can't click very fast anyway. Click "Interrupt" to stop.
(monkoutline) [
145.0 0.0 .moveto 145.0 17.5 .lineto 137.5 32.5 .lineto 142.5 57.5 .lineto 152.5 70.0 .lineto 135.0 70.0 .lineto 117.5 30.0 .lineto 97.5 25.0 .lineto 80.0 32.5 .lineto 52.5 72.5 .lineto 60.0 122.5 .lineto 22.5 202.5 .lineto 17.5 220.0 .lineto 25.0 235.0 .lineto 27.5 250.0 .lineto 37.5 262.5 .lineto 40.0 275.0 .lineto 40.0 285.0 .lineto 42.5 302.5 .lineto 52.5 312.5 .lineto 57.5 322.5 .lineto 67.5 330.0 .lineto 65.0 350.0 .lineto 62.5 377.5 .lineto 87.5 410.0 .lineto 107.5 432.5 .lineto 117.5 457.5 .lineto 147.5 492.5 .lineto 187.5 527.5 .lineto 217.5 525.0 .lineto 240.0 540.0 .lineto 252.5 545.0 .lineto 247.5 557.5 .lineto 252.5 565.0 .lineto 262.5 567.5 .lineto 267.5 575.0 .lineto 282.5 575.0 .lineto 275.0 592.5 .lineto 267.5 605.0 .lineto 260.0 612.5 .lineto 255.0 622.5 .lineto 255.0 632.5 .lineto 257.5 640.0 .lineto 257.5 655.0 .lineto 252.5 675.0 .lineto 252.5 692.5 .lineto 257.5 710.0 .lineto 277.5 742.5 .lineto 295.0 757.5 .lineto 312.5 767.5 .lineto 330.0 770.0 .lineto 347.5 775.0 .lineto 372.5 772.5 .lineto 392.5 762.5 .lineto 407.5 755.0 .lineto 422.5 745.0 .lineto 430.0 727.5 .lineto 435.0 702.5 .lineto 437.5 685.0 .lineto 440.0 670.0 .lineto 442.5 650.0 .lineto 442.5 615.0 .lineto 432.5 607.5 .lineto 430.0 585.0 .lineto 445.0 577.5 .lineto 502.5 530.0 .lineto 540.0 522.5 .lineto 587.5 452.5 .lineto 617.5 385.0 .lineto 630.0 345.0 .lineto 650.0 215.0 .lineto 650.0 195.0 .lineto 647.5 175.0 .lineto 635.0 160.0 .lineto 617.5 152.5 .lineto 600.0 125.0 .lineto 605.0 120.0 .lineto 602.5 112.5 .lineto 595.0 115.0 .lineto 590.0 85.0 .lineto 590.0 0.0 .lineto
502.5 632.5 .moveto 545.0 740.0 .lineto 575.0 632.5 .lineto 470.0 710.0 .lineto 602.5 712.5 .lineto
] .def
This makes an array of trajectories and saves it for future use
e monkPixelArray .setpacolor monkoutline .arraymaskfill
This draws the clipped monk
(redoutlinedmonk) {{.red .setcolor roundjoint 20 .setstrokewidth monkoutline .arraymaskstrokeclosed monkPixelArray .setpacolor monkoutline .arraymaskfill}.cvx .dosave}.cvx .def
This draws the clipped monk inside a red outline.
(smallmonk) {{.4 .scalet redoutlinedmonk}.cvx .dosave}.cvx .def
A smaller version.
(monkpersp) {{{.mouse 2 .copy .translatet 480 .exch .sub 480 .div .scalet .pop smallmonk}.cvx .dosave}.cvx .loop}.cvx .def
Just for fun