alexheretic / glyph-brush

Fast GPU cached text rendering
Apache License 2.0
688 stars 52 forks source link

Layout: text position translation #80

Closed dhardy closed 4 years ago

dhardy commented 4 years ago

I wish to implement text editing over glyph_brush, which requires text-position → coordinate translation (drawing edit marker) and vice-versa (mouse interaction). Currently it looks like this would be possible using GlyphCruncher::glyphs but far from ideal since a glyph is not a byte or even a char (e.g. spaces are skipped), thus glyph index != text index.

I'm not sure what the best way of achieving this is; perhaps rusttype::PositionedGlyph should track some type of index, or perhaps a separate method (redundantly recalculating positions) should be used (not so wasteful as it sounds, since only a small sub-set of drawn text is edited).

alexheretic commented 4 years ago

Generally what glyph_brush is trying to do is draw text fast. I'm hesitant to try to solve other problems. On the other hand storing a byte index with the glyph may not turn out to be difficult or affect the performance much. So I guess this idea needs some investigation.

Another option is to layout the glyphs manually and just get glyph_brush to generate vertices etc.

dhardy commented 4 years ago

IMHO drawing text fast is a good goal, and since at any one time only a small minority of text ever needs the position translation, a separate method to do that is probably the way to go.

In which case the questions are, (a) can this share code with the existing glyph positioner, and (b) is glyph_brush/glyph_brush_layout the place to host this?

LPeter1997 commented 4 years ago

I've hit this limitation while trying to implement a textbox. GlyphCruncher::glyphs takes me 90% of the way, but it ignores things like spaces. What's the status of this? Is a change/extension planned?

dhardy commented 4 years ago

@LPeter1997 my understanding now is that correctly computing glyph layout is a complex problem, which is only solved in a very limited way here, thus it makes sense to rely on some external crate to do that job in non-toy applications (or at least, ones with good internationlisation support).

The allsorts crate is the first Rust-native font shaper I am aware of, but using this with glyph-brush may still take some work (see this issue).

alexheretic commented 4 years ago

Right now glyph_brush isn't aimed to solve this directly.

However, you can position the glyphs yourself (recording spaces & whatever else you need) then give the positioned glyphs to glyph_brush for drawing, see https://docs.rs/glyph_brush/0.6.1/glyph_brush/struct.GlyphBrush.html#method.queue_pre_positioned

You don't benefit from the layout caching this way for obvious reasons.

alexheretic commented 4 years ago

The next version all laid out glyphs will have a section_index & byte_index.

alexheretic commented 4 years ago

With the 0.7 release this should be resolved

dhardy commented 4 years ago

@alexheretic there's one little issue: glyphs report their position and scale, but the scale is just the font scale, not the actual glyph size. Because of this the glyph iterator cannot be used to get position to the right of the last glyph.

There are workarounds, e.g. using the glyph_bounds method or simply adding a space afterwards, so this isn't a major issue.

alexheretic commented 4 years ago

@dhardy you can add the h_advance to the position to get that.

dhardy commented 4 years ago

Oh thanks. (Just realised neither of my suggested workarounds are reliable given multi-line text.)

dhardy commented 4 years ago

I have text editing mostly functional now thanks to this work. Unfortunately a number of hacks are needed to deal with multi-line text sections due to the omission of virtual "line-break" glyphs.

I get the impression one should really use an external line-splitter anyway (are there any hints on how to do this, given that it relies on text metrics?).