(Fit.JaM) =
(April 7, 1983 3:36 pm) =
(user) .dup .where {.pop .pop}{256 .dict .def}.ifelse .cvx .exec
user .begin

(/run){(Running ).print .dup .print .run (.)=}.cvx .def
(/loadbcd){(Loading ).print .dup .print .loadbcd (.)=}.cvx .def
(init) (
(JaMImager.jam)/run
(Fit.bcd)/loadbcd (FitJaM) .callinit FitJaM.InitAll
).cvx .def

(startup) (gets things started) {((/ivy/plass/hacks/cmr30.ac) FitFont 0 128 FitACRange (will fit a whole font and append the results to curve.log)) =
}/xdef
(ds)
(draws the samples)
(.drawsa)/xdef
(dss)
(draws all contours)
{.countcon {ds .nextcon}.cvx .rept}/xdef
(ms)
(marks the samples)
(1 .setmarksize .marksa)/xdef
(mss)
(marks all contours)
{.countcon {ms .nextcon}.cvx .rept}/xdef
(dc)
(draws the curve)
(.drawli)/xdef
(dcs)
(draws all curves)
{.countcon {dc .nextcon}.cvx .rept}/xdef
(mc)
(marks the joints along the curve)
(2 .setmarksize .markli)/xdef
(mcs)
(marks the joints along the curves)
{2 .setmarksize .countcon {.markli .nextcon}.cvx .rept}/xdef
(mn)
(marks the nodes with the normal lines)
(2 .setmarksize .marknodes)/xdef
(mns)
(marks all nodes with the normal lines)
(2 .setmarksize .countcon {.marknodes .nextcon}.cvx .rept)/xdef
(settangents)
(Set the tangents for sketched samples)
(4 .01 10 .settangents mn)/xdef
(grow)
(Grow a spline for sketched samples)
(.5 15 .grow cvtempstring .print ( knots) =)/xdef
(getAIS)
(Loads an AIS file for stroke tracing: takes a file name)
(.dup .setupais .drawmyais .ctraceopen)/xdef
(da)
(draws the current sampled image)
(.drawmyais)/xdef
(trace)
(Trace a stroke in sampled image: first touch tells start, second indicates initial direction)
(.resetsa .touch .touch 3 230 1000 .ctrace)/xdef
(resetmouse)
(Resets mouse clicks so they do nothing) (
(.track) {.pop .pop}.cvx .store
(.reddown) {.pop .pop}.cvx .store
(.redup) {.pop .pop}.cvx .store
(.yellowdown) {.pop .pop}.cvx .store
(.yellowup) {.pop .pop}.cvx .store
(.bluedown) {.pop .pop}.cvx .store
(.blueup) {.pop .pop}.cvx .store
)/xdef
(edit)
(Point edit: red inserts, yellow moves, blue deletes) (resetmouse
(Point edit: red inserts, yellow moves, blue deletes
) .print
(.yellowdown) {.selectsa .thetan .deletesa e ms}.cvx .store
(.yellowup) {.insertsa .nodesa .tansa e ms}.cvx .store
(.blueup) {.selectsa .deletesa e ms}.cvx .store
(.reddown) {.selectsa}.cvx .store
(.redup) {.insertbetween e ms}.cvx .store
e ms
)/xdef
(nodes)
(node edit: red sets a node, yellow sets a tangent, blue removes a node) (resetmouse
(node edit: red sets a node, yellow sets a tangent, blue removes a node
) .print
(.redup) (.selectsa .true .nodesa mn).cvx .def
(.yellowdown) (.selectsa).cvx .def
(.yellowup) (.thesa Complex.Sub .tansa noderefresh).cvx .def
(.blueup) (.selectsa .false .nodesa noderefresh).cvx .def
noderefresh
)/xdef
(ht) (make tangent horizontal at the current node)
{1 0 .tansa noderefresh}/xdef
(vt) (make tangent horizontal at the current node)
{0 1 .tansa noderefresh}/xdef
(ft) (make tangent free at the current node)
{0 0 .tansa noderefresh}/xdef
(cusps)
(cusp edit: red sets a cusp, yellow sets a tangent, blue removes a cusp) (resetmouse
(cusp edit: red sets a cusp, yellow sets a tangent, blue removes a cusp
) .print
(.redup) (.selectsa .true .cuspsa mn).cvx .def
(.yellowup) (.selectsa .true .cuspnode mn).cvx .def
(.blueup) (.selectsa .false .cuspsa noderefresh).cvx .def
noderefresh
)/xdef
(noderefresh) (e ms mn).cvx .def
(allnodes)
(makes every sample a node)
(.homesa .countsa {.nextsa .true .nodesa}.cvx .rept noderefresh)/xdef
(nonodes)
(removes all nodes except endpoints)
(.homesa .countsa 2 .sub .nextsa {.nextsa .false .nodesa}.cvx .rept noderefresh)/xdef
(sketch)
(Sketches a curve with the mouse) (
(Sketch a curve
) .print
.resetsa resetmouse
(.reddown) {2 .copy .setcp .addsa}.cvx .store
(.track) {2 .copy .drawto .addsa}.cvx .store
)/xdef
(transform)
(Transforms samples: red moves and sets origin, yellow scales and blue rotates) {resetmouse
(Transforms samples: red moves and sets origin, yellow scales and blue rotates
) .print
(.reddown) {}.cvx .store
(.redup) {2 .copy (rotorgy) .exch .store (rotorgx) .exch .store 4 2 .roll Complex.Sub translatecontours e transrefresh}.cvx .store
(.yellowdown) {orgtrans orgrel}.cvx .store
(.yellowup) {orgrel 4 2 .roll Complex.Div Complex.Abs 0 scalecontours unorgtrans e transrefresh}.cvx .store
(.bluedown) {orgtrans orgrel}.cvx .store
(.blueup) {orgrel 4 2 .roll Complex.Div 2 .copy Complex.Abs 0 Complex.Div scalecontours unorgtrans e transrefresh}.cvx .store
(rotorgx) 0 .store 0 (rotorgy) 0 .store
transrefresh}/xdef
(transrefresh) {e dss rotorgx rotorgy dot .pop .pop}.cvx .def
(orgrel) (rotorgx rotorgy 4 2 .roll Complex.Sub).cvx .def
(orgtrans) {rotorgx .neg rotorgy .neg translatecontours}.cvx .def
(unorgtrans) {rotorgx rotorgy translatecontours}.cvx .def
(rotorgx) 0 .def
(rotorgy) 0 .def
(degrees)
(Converts degrees to something the scaler likes)
(180.0 .div 3.1415926 .mul 0 .exch Complex.Exp)/xdef
(rotate)
(rotates the samples by degrees)
(degrees orgtrans scalecontours unorgtrans e transrefresh)/xdef
(scale)
(Scales the samples)
(0 orgtrans scalecontours unorgtrans e transrefresh)/xdef
(scalecontours)
(Scales/rotates all the contours)
{.countcon {2 .copy .scalesa .nextcon}.cvx .rept .pop .pop}/xdef
(translatecontours)
(Tranlates all the contours)
{.countcon {2 .copy .transa .nextcon}.cvx .rept .pop .pop}/xdef
(setfirst)
(sets the position of the first sample)
{.homesa .nextsa .deletesa .touch .selectsa .makefirstsa .homesa .nextsa .thesa .addsa}/xdef
(corners)
(touch the corners)
{resetmouse e ms
 (.reddown) {.selectsa .cornersa .true .nodesa e ms}.cvx .def
 (.bluedown) {.homesa .nextsa .deletesa .selectsa .makefirstsa .homesa .nextsa .thesa .addsa .homesa .nextsa .true .nodesa .homesa .prevsa .true .nodesa}.cvx .def
 }/xdef
(MoveHomeToLowerLeft)
{.homesa .nextsa .deletesa 0 0 .selectsa .makefirstsa .homesa .nextsa .thesa .addsa .homesa .nextsa .true .nodesa .homesa .prevsa .true .nodesa}.cvx .def
(MoveHomeToACorner)
{.homesa .nextsa .deletesa FindACorner .makefirstsa .homesa .nextsa .thesa .addsa .homesa .nextsa .true .nodesa .homesa .prevsa .true .nodesa}.cvx .def
(FindACorner)
{.homesa .countsa {.nextsa IsCorner {.exit}/if}.cvx .rept}.cvx .def
(IsCorner)
{.thetan .pop Complex.Abs 0 .eq .thetan .exch .pop .exch .pop .and}.cvx .def
(nc)
(use next contour)
{.nextcon ms}/xdef
(closeup)
(For taking a close look at the result. Use the mouse to point near the area you are interested in.) {
.initdc resetmouse
0 0 (closey) .exch .store (closex) .exch .store 0 0 showclose
(.track) {2 .copy showclose closex closey showclose (closey) .exch .store (closex) .exch .store}.cvx .def
}/xdef
(showclose) {.neg .exch .neg .exch .setinvert 10 10 .scale .translate mss dcs mns .initdc}.cvx .def
(insertcorners)
(puts in corners)
{.countsa .homesa {.nextsa 0 0 .insertsa .prevsa .cornersa checkduplicate}.cvx .rept}/xdef
(checkduplicate) {.thesa 0 0 areclose .thesa theprevsa areclose .thesa thenextsa areclose .or .or {.deletesa .prevsa}/if .nextsa}.cvx .def
(areclose) {Complex.Sub Complex.Abs 0.1 .lt}.cvx .def
(theprevsa) {.prevsa .thesa .nextsa}.cvx .def
(thenextsa) {.nextsa .thesa .prevsa}.cvx .def
(sharpencorners)
{.countsa .homesa {.nextsa IsCorner {.cornersa}/if}.cvx .rept}.cvx .def
(k?) (counts the knots)
{ 0 (8 {.pop}.cvx .rept 1 .add).cvx .foralllinks cvtempstring .print ( knots) =}/xdef
(printpoint) {.exch cvtempstring .print ( ).print cvtempstring .print ( ).print}.cvx .def
(newcontour) {(initmoveto) {logpoint (.movetonext) .noter (initmoveto) {.pop .pop}.cvx .def}.cvx .def}.cvx .def
(HandFitContour) {.dup (curContour) .exch .store
 .setsa 3 0 .scalesa edit}.cvx .def
(gp) {.touch 2 .copy .exch cvtempstring .print ( ).print cvtempstring .print ( ).print}.cvx .def
(sk) {gp .moveto (.moveto) = {gp gp gp .curveto (.curveto) = .getpos 0 .drawpath .moveto}.cvx .loop}.cvx .def