requires: {#QuadraticBezierSegment. #CubicBezierSegment. #Point}. "provides: {#UserPath}." "This needs renamed" Graphics addPrototype: #UserPath derivedFrom: {Trace}. UserPath addSlot: #currentPoint valued: Point origin. UserPath addSlot: #startPoint valued: Point origin. UserPath addSlot: #segments valued: ExtensibleArray newEmpty. UserPath addSlot: #closed valued: False. up@(UserPath traits) copy [|newUP| newUP: up clone. newUP segments: up segments copy. newUP closed: up closed. newUP currentPoint: up currentPoint. newUP startPoint: up startPoint. newUP ]. up@(UserPath traits) penFlatness [up context penFlatness]. up@(UserPath traits) curveFlatness [up context curveFlatness]. up@(UserPath traits) penTo: p@(Point traits) "Sets the starting point" [ up currentPoint: p. up startPoint: p. up ]. up@(UserPath traits) lineTo: p@(Point traits) "Add a LineSegment to an absolute Point" [ up segments add: (LineSegment newFrom: up currentPoint to: p). up currentPoint: p. up ]. up@(UserPath traits) relativeLineTo: p@(Point traits) "Add a LineSegment to a relative Point" [|ap| ap: p + up currentPoint. up lineTo: ap. up ]. up@(UserPath traits) curveTo: p@(Point traits) via: v1@(Point traits) via: v2@(Point traits) "Add a cubic bezier to the path." [ up segments add: (CubicBezierSegment newFrom: up currentPoint to: p via: v1 via: v2). up currentPoint: p. up ]. up@(UserPath traits) curveTo: p@(Point traits) via: v@(Point traits) "Add a quadratic bezier to the path." [ up segments add: (QuadraticBezierSegment newFrom: up currentPoint to: p via: v). up currentPoint: p. up ]. up@(UserPath traits) closePath "Draws a line from the current point to the start point" [ "TODO: Check if the current and endpoints are the same first" up segments add: (LineSegment newFrom: up currentPoint to: up startPoint). up currentPoint: up startPoint. up closed: True. up ]. up@(UserPath traits) end "Ends this path" []. up@(UserPath traits) stroke "Strokes the current path" "Converts the UserPath into one or more PolyLines, strokes, caps and joins them, then passes them as polygons to the tessilator" [|newP pen| pen: (Pen newWidth: up penWidth flatness: up penFlatness). newP: up segments collect: [|:each| each strokeWithPen: pen flatness: up curveFlatness]. newP doAllButLast: [|:each| each joinToNext]. up closed ifTrue: [newP joinLastToFirst] ifFalse: [newP cap]. newP: (newP as: Polygon). newP renderOn: up medium. ]. up@(UserPath traits) fill "Turns the path into a filled polygon" "TODO: Beware of gaps" [|poly| poly: (up segments as: Polygon). poly renderOn: up medium. up ]. "Draw Shapes on a Surface using a Medium" "Shape = geometric object" "Surface = anything you can draw on" "Medium = the drawing context" "A Surface can provide an appropriate Medium" " shape renderOn: medium &pen: aWeirdConvexPolygon &ink: aFunkyPattern. shape renderFilledOn: medium &ink: Color red. StandardMedium - a platform independent medium which is converted to platform specific ones when used X11Medium - a medium which knows how to draw on X11 Drawables "