
Arrow heads in Sketch
=====================


The situation in 0.6.x
----------------------

In 0.6, an arrow head is given as a single bezier path that is either
stroked or filled with the line color of the object it's associated
with. 

The coordinates of the path are given in the arrow coordinate system
which is rotated and translated such that the arrow's tip points in the
direction of the positive x-axis and the origin coincides with the
end-point of the curve. The unit is the line width of the object.


The Problem
-----------

One disadvantage of this is that the tip of the arrow is normally not
exactly the end-point of the curve and since the end-point is snapped to
the grid the arrow tip is not on the grid (or other points Sketch snaps
to).

The tip can't be on the end-point with the current arrow model because
the line would protrude from the arrow tip like this:


                            |\
                            | \
                            |  \
                            |   \
 -- -- ---------------------+----\--+
                            |     \ |
                            |      \|
                            |      /|
                            |     / |
 -- -- ---------------------+----/--+
                            |   /
                            |  /
                            | /
                            |/



Possible remedies
-----------------

So far, I've come up with two different solutions:

A. Associate a parameter with an arrow tip description that defines how
   far the curve has to be foreshortened. This way, a curve will stop
   shortly before the real endpoint of the curve and the arrow tip can
   be exactly at the endpoint.

B. Have an arrow property that defines where exactly the tip is in the
   arrow coordinate system. With this information, Sketch can determine
   the real position of the arrow tip and use that for snapping if the
   user drags a start or end-point of a curve.

In Sketch 0.7.4, I've implemented both variants and it seems that both
have advantages and disadvantages:

Solution A requires considerable changes to the drawing code to make
sure that drawing stops a little before the end points while B requires
no changes in the drawing code.

A is easier to use in my opinion because the tip and the end-point
coincide. This is an advantage when dragging the end-point since the
arrow head is not visible during a drag (although this could be changed,
of course) and when moving the control-point that controls the tangent
at the end-point because the tip doesn't move and stays on the grid.
With B the tip would move when the control point is changed.

B is more flexible than A because it allows for asymmetric arrow heads
where the tip is not located on the x-axis in the arrow coordinate
system. With A, the tip has to be at the origin (of the arrow coordinate
system) if it is to snap to the grid.



Conclusion
----------

Both solutions have advantages and disadvantages and they're not
mutually exclusive, so it would seem like a good idea to implement them
both. I'm not really comfortable with that, though, for several reasons.

All changes that affect the file format will have to be supported in
future versions of Sketch to ensure backwards compatability. For
solution B this would be trivial as one could simply ignore the
additional information, for A this might require more work if the arrow
semantics should change.

There might be a better solution that is even better than A and B
together.
