fn layout_text(&mut self, text: &Text) -> TextLayoutState {
        let mut glyph_ids = Vec::new();
        let mut xs = Vec::new();
        let mut break_hints = Vec::new();
        let mut breaks = Vec::new();
        let mut x = 0.;

        let mut found_space = false;
        // where the current breakpoint starts
        let mut hint = None;

        // TODO: at least have a concept of shaping
        // (different number of chars vs. glyphs depending on their neighbours)

        // all glyphs are kept because of text selection
        for (i, ch) in text.text.chars().enumerate() {
            // TODO: atlasing
            let glyph_id = ch;
            let font_glyph = self.font_glyphs.entry(glyph_id).or_insert_with(|| {
              error!("no glyph {:?}", glyph_id);
              MISSING_GLYPH
            });

            glyph_ids.push(glyph_id);
            xs.push(x);

            // TODO: FSM could be (a bit) more readable
            // but it's not that hard, it just adds hint after each space
            // ignoring any adjacent whitespace
            if ch == ' ' {
                if !found_space {
                    found_space = true;

                    if let Some(i) = hint {
                        break_hints.push((i, x));
                        hint = None;
                    }
                }
            } else if ch == '\n' {
                if let Some(i) = hint {
                    break_hints.push((i, x));
                    hint = None;
                }

                break_hints.push((i, std::f32::MAX));
                breaks.push(i);
                found_space = false;
            } else if found_space {
                hint = Some(i);
                found_space = false;
            }

            x += font_glyph.advance * text.font_size;
        }

        if let Some(i) = hint {
            break_hints.push((i, x));
        }

        TextLayoutState {
            font_size: text.font_size,
            line_height: text.line_height,

            single_line_width: x,

            glyph_ids,
            xs,
            break_hints,
            breaks,
        }
    }
// do initial layout, \n is respected but any other wrapping is
// left to be done later
//
// not sure if it will work out but the idea is that basic
// layout can be done even before max_width is known
//
// it could be noticable with more complex text shaping 
// and maybe some of this can be done in parallel also
//
// when measure is called, we can compute breaks quickly and
// return the new size so the layout can continue
//
// we could also start building (in other thread?)
// the buffer with glyphs, because position & color is in uniforms
// and can be returned
do initial layout, \n is respected but any other wrapping is
left to be done later

not sure if it will work out but the idea is that basic
layout can be done even before max_width is known

it could be noticable with more complex text shaping
and maybe some of this can be done in parallel also

when measure is called, we can compute breaks quickly and
return the new size so the layout can continue

we could also start building (in other thread?)
the buffer with glyphs, because position & color is in uniforms
and can be returned
do initial layout \ n is respected but any other wrapping is left to be done later not sure if it will work out but the idea is that basic layout can be done even before max_width is known it could be noticable with more complex text shaping and maybe some of this can be done in parallel also when measure is called we can compute breaks quickly and return the new size so the layout can continue we could also start building ( in other thread? ) the buffer with glyphs because position & color is in uniforms and can be returned
fn layout_text(&mut self, text: &Text) -> TextLayoutState {
        let mut glyph_ids = Vec::new();
        let mut xs = Vec::new();
        let mut break_hints = Vec::new();
        let mut breaks = Vec::new();
        let mut x = 0.;
        let mut found_space = false;
        // where the current breakpoint starts
        let mut hint = None;
        // TODO: at least have a concept of shaping
        // (different number of chars vs. glyphs depending on their neighbours)
        // all glyphs are kept because of text selection
        for (i, ch) in text.text.chars().enumerate() {
            // TODO: atlasing
            let glyph_id = ch;
            let font_glyph = self.font_glyphs.entry(glyph_id).or_insert_with(|| {
              error!("no glyph {:?}", glyph_id);
              MISSING_GLYPH
            });
            glyph_ids.push(glyph_id);
            xs.push(x);
            // TODO: FSM could be (a bit) more readable
            // but it's not that hard, it just adds hint after each space
            // ignoring any adjacent whitespace
            if ch == ' ' {
                if !found_space {
                    found_space = true;
                    if let Some(i) = hint {
                        break_hints.push((i, x));
                        hint = None;
                    }
                }
            } else if ch == '\n' {
                if let Some(i) = hint {
                    break_hints.push((i, x));
                    hint = None;
                }
                break_hints.push((i, std::f32::MAX));
                breaks.push(i);
                found_space = false;
            } else if found_space {
                hint = Some(i);
                found_space = false;
            }
            x += font_glyph.advance * text.font_size;
        }
        if let Some(i) = hint {
            break_hints.push((i, x));
        }
        TextLayoutState {
            font_size: text.font_size,
            line_height: text.line_height,
            single_line_width: x,
            glyph_ids,
            xs,
            break_hints,
            breaks,
        }
    }
fn layout_text ( & mut self , text : & Text ) -> TextLayoutState { let mut glyph_ids = Vec :: new ( ) ; let mut xs = Vec :: new ( ) ; let mut break_hints = Vec :: new ( ) ; let mut breaks = Vec :: new ( ) ; let mut x = 0. ; let mut found_space = false ; // where the current breakpoint starts let mut hint = None ; // TODO: at least have a concept of shaping // (different number of chars vs. glyphs depending on their neighbours) // all glyphs are kept because of text selection for ( i , ch ) in text . text . chars ( ) . enumerate ( ) { // TODO: atlasing let glyph_id = ch ; let font_glyph = self . font_glyphs . entry ( glyph_id ) . or_insert_with ( | | { error ! ( " " glyph_id ) ; MISSING_GLYPH } ) ; glyph_ids . push ( glyph_id ) ; xs . push ( x ) ; // TODO: FSM could be (a bit) more readable // but it's not that hard, it just adds hint after each space // ignoring any adjacent whitespace if ch == ' ' { if ! found_space { found_space = true ; if let Some ( i ) = hint { break_hints . push ( ( i , x ) ) ; hint = None ; } } } else if ch == '\n' { if let Some ( i ) = hint { break_hints . push ( ( i , x ) ) ; hint = None ; } break_hints . push ( ( i , std :: f32 :: MAX ) ) ; breaks . push ( i ) ; found_space = false ; } else if found_space { hint = Some ( i ) ; found_space = false ; } x += font_glyph . advance * text . font_size ; } if let Some ( i ) = hint { break_hints . push ( ( i , x ) ) ; } TextLayoutState { font_size : text . font_size , line_height : text . line_height , single_line_width : x , glyph_ids , xs , break_hints , breaks , } }
do initial layout, \n is respected but any other wrapping is
left to be done later
do initial layout \ n is respected but any other wrapping is left to be done later
&mut self
text
&Text
&mut self
text
&Text