In the last post, we didn’t say how exactly we go from
Frag to pixels. One problem is because we want to support
LineFrag.Text with different text sizes, we need to align texts in one line by baseline.
After some experiment, the implementation is the most simple one:
class Line(pad: Float, items: Seq[LineFrag.Text]) class Page(lines: Seq[Line]) case class Pos(line: Int, cursor: Int)
Then each line can be measured. Then drawn.
During measuring, each frag will cache it’s start/end position in the page using type
Pos. This way from pixels in screen, we can easily lookup which line and
LineFrag.Text is user pointing to, and then from information in
Frag we can get which fragment does it corresponds to.
As we said before, the algorithm to line break is incremental. We also try to make sure we don’t produce
Line when unnecessary by caching
Frag which corresponds to entire lines.
Lines starts with red color is lines needs to be redrawn when the text at the cursor is changed, most line is cached so layout after small text edit is super fast:
Before this change, I tried to work directly with
Frag and give each
Frag a position relative to parent
Frag and width and height, and draw directly using these information. This creates overly complicated and fragile code. So I guess the most direct way to program something is almost always the best.