pub fn drawing_with_laid_out_text<InStream: 'static+Send+Unpin+Stream<Item=Draw>>(draw_stream: InStream) -> impl Send+Unpin+Stream<Item=Draw> {
    generator_stream(move |yield_value| async move {
        let mut draw_stream         = draw_stream;

        // State of this stream
        let mut font_map            = HashMap::new();
        let mut font_size           = HashMap::new();
        let mut current_line        = None;
        let mut current_font        = None;
        let (mut x_pos, mut y_pos)  = (0.0, 0.0);
        let mut alignment           = TextAlignment::Left;

        // Read from the drawing stream
        while let Some(draw) = draw_stream.next().await {
            match draw {
                Draw::Font(font_id, FontOp::UseFontDefinition(font_defn)) => {
                    // Defining new fonts interrupts any existing text layout
                    current_line = None;
                    current_font = None;

                    // Store this font definition
                    font_map.insert(font_id, Arc::clone(&font_defn));
                    font_size.insert(font_id, 12.0);

                    // Send the font to the next part of the stream
                    yield_value(Draw::Font(font_id, FontOp::UseFontDefinition(font_defn))).await;
                }

                Draw::Font(font_id, FontOp::FontSize(new_size)) => {
                    // If we're changing the size of the active font, restart the layout with the new size
                    if current_font == Some(font_id) {
                        current_line = current_line
                            .map(|line: CanvasFontLineLayout| {
                                let font = line.font();
                                line.continue_with_new_font(font_id, &font, new_size)
                            });
                    }

                    // Set up the new size
                    font_size.insert(font_id, new_size);

                    yield_value(Draw::Font(font_id, FontOp::FontSize(new_size))).await;
                }

                Draw::BeginLineLayout(x, y, align)   => {
                    // If we're laying out text already, this discards that layout
                    current_line    = None;
                    current_font    = None;

                    // Set up the layout for the next set of text
                    x_pos           = x;
                    y_pos           = y;
                    alignment       = align;
                }

                Draw::Font(font_id, FontOp::LayoutText(text)) => {
                    // Update the current font
                    if current_font != Some(font_id) {
                        if let (Some(new_font), Some(font_size)) = (font_map.get(&font_id), font_size.get(&font_id)) {
                            let last_font   = current_font.unwrap_or(FontId(0));
                            let new_font    = Arc::clone(new_font);
                            let font_size   = *font_size;

                            current_line = current_line
                                .map(|line: CanvasFontLineLayout| {
                                    line.continue_with_new_font(last_font, &new_font, font_size)
                                }).or_else(|| {
                                    Some(CanvasFontLineLayout::new(&new_font, font_size))
                                });
                            current_font = Some(font_id);
                        }
                    }

                    // Lay out the text
                    current_line.as_mut().map(|line| line.add_text(&text));
                }

                Draw::DrawLaidOutText => {
                    if let Some(layout) = mem::take(&mut current_line) {
                        // Align the layout
                        let mut layout = layout;
                        layout.align(x_pos, y_pos, alignment);

                        if let Some(current_font) = mem::take(&mut current_font) {
                            // Convert to drawing actions, and send those
                            let drawing = layout.to_drawing(current_font);

                            for draw in drawing {
                                yield_value(draw).await;
                            }
                        }
                    }
                },

                Draw::FillColor(fill_color) => {
                    // This is added as a drawing instruction to the current layout
                    if let Some(current_line) = &mut current_line {
                        current_line.draw(iter::once(Draw::FillColor(fill_color.clone())));
                    }

                    yield_value(Draw::FillColor(fill_color)).await;
                },

                Draw::DrawText(font_id, text, x, y) => {
                    if let (Some(font), Some(font_size)) = (font_map.get(&font_id), font_size.get(&font_id)) {
                        // This is just a straightforward immediate layout of the text as glyphs
                        let mut layout = CanvasFontLineLayout::new(font, *font_size);

                        // Lay out the text
                        layout.add_text(&text);

                        // Align it at the requested position
                        layout.align(x, y, TextAlignment::Left);

                        // Convert to glyph drawing instructions, and send those on to the next stage
                        let drawing = layout.to_drawing(font_id);
                        for draw in drawing {
                            yield_value(draw).await;
                        }
                    }
                }

                Draw::Layer(_) => {
                    // These instructions interrupt text layout
                    current_line = None;
                    current_font = None;

                    yield_value(draw).await;
                }

                Draw::Sprite(_) => {
                    // These instructions interrupt text layout
                    current_line = None;
                    current_font = None;

                    yield_value(draw).await;
                }

                Draw::ClearLayer => {
                    // These instructions interrupt text layout
                    current_line = None;
                    current_font = None;

                    yield_value(draw).await;
                }

                Draw::ClearCanvas(_) => {
                    // Clear state
                    font_map        = HashMap::new();
                    current_line    = None;
                    current_font    = None;

                    yield_value(draw).await;
                }

                // Default action is just to pass the drawing on
                _ => {
                    yield_value(draw).await;
                }
            }
        }
    })
}
///
/// Given a stream with font instructions, replaces any layout instruction (eg, `Draw::DrawText()`) with glyph
/// rendering instructions
///
Given a stream with font instructions, replaces any layout instruction `) with glyph
rendering instructions
Given a stream with font instructions replaces any layout instruction ` ) with glyph rendering instructions
pub fn drawing_with_laid_out_text<InStream: 'static+Send+Unpin+Stream<Item=Draw>>(draw_stream: InStream) -> impl Send+Unpin+Stream<Item=Draw> {
    generator_stream(move |yield_value| async move {
        let mut draw_stream         = draw_stream;
        // State of this stream
        let mut font_map            = HashMap::new();
        let mut font_size           = HashMap::new();
        let mut current_line        = None;
        let mut current_font        = None;
        let (mut x_pos, mut y_pos)  = (0.0, 0.0);
        let mut alignment           = TextAlignment::Left;
        // Read from the drawing stream
        while let Some(draw) = draw_stream.next().await {
            match draw {
                Draw::Font(font_id, FontOp::UseFontDefinition(font_defn)) => {
                    // Defining new fonts interrupts any existing text layout
                    current_line = None;
                    current_font = None;
                    // Store this font definition
                    font_map.insert(font_id, Arc::clone(&font_defn));
                    font_size.insert(font_id, 12.0);
                    // Send the font to the next part of the stream
                    yield_value(Draw::Font(font_id, FontOp::UseFontDefinition(font_defn))).await;
                }
                Draw::Font(font_id, FontOp::FontSize(new_size)) => {
                    // If we're changing the size of the active font, restart the layout with the new size
                    if current_font == Some(font_id) {
                        current_line = current_line
                            .map(|line: CanvasFontLineLayout| {
                                let font = line.font();
                                line.continue_with_new_font(font_id, &font, new_size)
                            });
                    }
                    // Set up the new size
                    font_size.insert(font_id, new_size);
                    yield_value(Draw::Font(font_id, FontOp::FontSize(new_size))).await;
                }
                Draw::BeginLineLayout(x, y, align)   => {
                    // If we're laying out text already, this discards that layout
                    current_line    = None;
                    current_font    = None;
                    // Set up the layout for the next set of text
                    x_pos           = x;
                    y_pos           = y;
                    alignment       = align;
                }
                Draw::Font(font_id, FontOp::LayoutText(text)) => {
                    // Update the current font
                    if current_font != Some(font_id) {
                        if let (Some(new_font), Some(font_size)) = (font_map.get(&font_id), font_size.get(&font_id)) {
                            let last_font   = current_font.unwrap_or(FontId(0));
                            let new_font    = Arc::clone(new_font);
                            let font_size   = *font_size;
                            current_line = current_line
                                .map(|line: CanvasFontLineLayout| {
                                    line.continue_with_new_font(last_font, &new_font, font_size)
                                }).or_else(|| {
                                    Some(CanvasFontLineLayout::new(&new_font, font_size))
                                });
                            current_font = Some(font_id);
                        }
                    }
                    // Lay out the text
                    current_line.as_mut().map(|line| line.add_text(&text));
                }
                Draw::DrawLaidOutText => {
                    if let Some(layout) = mem::take(&mut current_line) {
                        // Align the layout
                        let mut layout = layout;
                        layout.align(x_pos, y_pos, alignment);
                        if let Some(current_font) = mem::take(&mut current_font) {
                            // Convert to drawing actions, and send those
                            let drawing = layout.to_drawing(current_font);
                            for draw in drawing {
                                yield_value(draw).await;
                            }
                        }
                    }
                },
                Draw::FillColor(fill_color) => {
                    // This is added as a drawing instruction to the current layout
                    if let Some(current_line) = &mut current_line {
                        current_line.draw(iter::once(Draw::FillColor(fill_color.clone())));
                    }
                    yield_value(Draw::FillColor(fill_color)).await;
                },
                Draw::DrawText(font_id, text, x, y) => {
                    if let (Some(font), Some(font_size)) = (font_map.get(&font_id), font_size.get(&font_id)) {
                        // This is just a straightforward immediate layout of the text as glyphs
                        let mut layout = CanvasFontLineLayout::new(font, *font_size);
                        // Lay out the text
                        layout.add_text(&text);
                        // Align it at the requested position
                        layout.align(x, y, TextAlignment::Left);
                        // Convert to glyph drawing instructions, and send those on to the next stage
                        let drawing = layout.to_drawing(font_id);
                        for draw in drawing {
                            yield_value(draw).await;
                        }
                    }
                }
                Draw::Layer(_) => {
                    // These instructions interrupt text layout
                    current_line = None;
                    current_font = None;
                    yield_value(draw).await;
                }
                Draw::Sprite(_) => {
                    // These instructions interrupt text layout
                    current_line = None;
                    current_font = None;
                    yield_value(draw).await;
                }
                Draw::ClearLayer => {
                    // These instructions interrupt text layout
                    current_line = None;
                    current_font = None;
                    yield_value(draw).await;
                }
                Draw::ClearCanvas(_) => {
                    // Clear state
                    font_map        = HashMap::new();
                    current_line    = None;
                    current_font    = None;
                    yield_value(draw).await;
                }
                // Default action is just to pass the drawing on
                _ => {
                    yield_value(draw).await;
                }
            }
        }
    })
}
pub fn drawing_with_laid_out_text < InStream : ' static + Send + Unpin + Stream < Item = Draw > > ( draw_stream : InStream ) -> impl Send + Unpin + Stream < Item = Draw > { generator_stream ( move | yield_value | async move { let mut draw_stream = draw_stream ; // State of this stream let mut font_map = HashMap :: new ( ) ; let mut font_size = HashMap :: new ( ) ; let mut current_line = None ; let mut current_font = None ; let ( mut x_pos , mut y_pos ) = ( 0.0 , 0.0 ) ; let mut alignment = TextAlignment :: Left ; // Read from the drawing stream while let Some ( draw ) = draw_stream . next ( ) . await { match draw { Draw :: Font ( font_id , FontOp :: UseFontDefinition ( font_defn ) ) => { // Defining new fonts interrupts any existing text layout current_line = None ; current_font = None ; // Store this font definition font_map . insert ( font_id , Arc :: clone ( & font_defn ) ) ; font_size . insert ( font_id , 12.0 ) ; // Send the font to the next part of the stream yield_value ( Draw :: Font ( font_id , FontOp :: UseFontDefinition ( font_defn ) ) ) . await ; } Draw :: Font ( font_id , FontOp :: FontSize ( new_size ) ) => { // If we're changing the size of the active font, restart the layout with the new size if current_font == Some ( font_id ) { current_line = current_line . map ( | line : CanvasFontLineLayout | { let font = line . font ( ) ; line . continue_with_new_font ( font_id , & font , new_size ) } ) ; } // Set up the new size font_size . insert ( font_id , new_size ) ; yield_value ( Draw :: Font ( font_id , FontOp :: FontSize ( new_size ) ) ) . await ; } Draw :: BeginLineLayout ( x , y , align ) => { // If we're laying out text already, this discards that layout current_line = None ; current_font = None ; // Set up the layout for the next set of text x_pos = x ; y_pos = y ; alignment = align ; } Draw :: Font ( font_id , FontOp :: LayoutText ( text ) ) => { // Update the current font if current_font != Some ( font_id ) { if let ( Some ( new_font ) , Some ( font_size ) ) = ( font_map . get ( & font_id ) , font_size . get ( & font_id ) ) { let last_font = current_font . unwrap_or ( FontId ( 0 ) ) ; let new_font = Arc :: clone ( new_font ) ; let font_size = * font_size ; current_line = current_line . map ( | line : CanvasFontLineLayout | { line . continue_with_new_font ( last_font , & new_font , font_size ) } ) . or_else ( | | { Some ( CanvasFontLineLayout :: new ( & new_font , font_size ) ) } ) ; current_font = Some ( font_id ) ; } } // Lay out the text current_line . as_mut ( ) . map ( | line | line . add_text ( & text ) ) ; } Draw :: DrawLaidOutText => { if let Some ( layout ) = mem :: take ( & mut current_line ) { // Align the layout let mut layout = layout ; layout . align ( x_pos , y_pos , alignment ) ; if let Some ( current_font ) = mem :: take ( & mut current_font ) { // Convert to drawing actions, and send those let drawing = layout . to_drawing ( current_font ) ; for draw in drawing { yield_value ( draw ) . await ; } } } } , Draw :: FillColor ( fill_color ) => { // This is added as a drawing instruction to the current layout if let Some ( current_line ) = & mut current_line { current_line . draw ( iter :: once ( Draw :: FillColor ( fill_color . clone ( ) ) ) ) ; } yield_value ( Draw :: FillColor ( fill_color ) ) . await ; } , Draw :: DrawText ( font_id , text , x , y ) => { if let ( Some ( font ) , Some ( font_size ) ) = ( font_map . get ( & font_id ) , font_size . get ( & font_id ) ) { // This is just a straightforward immediate layout of the text as glyphs let mut layout = CanvasFontLineLayout :: new ( font , * font_size ) ; // Lay out the text layout . add_text ( & text ) ; // Align it at the requested position layout . align ( x , y , TextAlignment :: Left ) ; // Convert to glyph drawing instructions, and send those on to the next stage let drawing = layout . to_drawing ( font_id ) ; for draw in drawing { yield_value ( draw ) . await ; } } } Draw :: Layer ( _ ) => { // These instructions interrupt text layout current_line = None ; current_font = None ; yield_value ( draw ) . await ; } Draw :: Sprite ( _ ) => { // These instructions interrupt text layout current_line = None ; current_font = None ; yield_value ( draw ) . await ; } Draw :: ClearLayer => { // These instructions interrupt text layout current_line = None ; current_font = None ; yield_value ( draw ) . await ; } Draw :: ClearCanvas ( _ ) => { // Clear state font_map = HashMap :: new ( ) ; current_line = None ; current_font = None ; yield_value ( draw ) . await ; } // Default action is just to pass the drawing on _ => { yield_value ( draw ) . await ; } } } } ) }
Given a stream with font instructions, replaces any layout instruction (eg, `Draw::DrawText()`) with glyph
rendering instructions
Given a stream with font instructions replaces any layout instruction ( eg ` Draw :: DrawText () ` ) with glyph rendering instructions
draw_stream
InStream