How to provide storage for borrowed structures?

Thanks very much for the explanation. It's a lot of what I suspected but didn't want to hear, and this has helped me a lot.

This topic is over but I do want to note the solution I've kind of come about. At least this is the work in progress one:

  • I have a TextLayoutContext that contains parley data
  • I have a GlyphStorage structure that contains rendered glyphs
  • I pass the glyph storage and some text to the layout context's layout_text function
  • The TextLayoutContext then passes data to a GlyphRenderer it creates that handles rasterization
  • The GlyphRenderer returns a GlyphKey used for GlyphStorage

This allows the data to be borrowed properly, but for performance reasons GlyphRenderer will only lazily render glyphs by checking the storage and will only lazily create the per-font data.

The only wart here is my use of unwrap:

    fn gen_skrifa_data(&mut self) -> Result<&SkrifaData<'a>, GlyphRendererError> {
        match self.skrifa_data {
            Some(ref data) => return Ok(&data),
            _ => {}
        }
        let params = self.font_params;
        let skrifa_coords = params
            .normalized_coords
            .iter()
            .map(|coord| NormalizedCoord::from_bits(*coord))
            .collect::<Vec<_>>();
        let font_ref = FontRef::from_index(params.font_data, params.font_index)?;
        let location_ref = LocationRef::new(&skrifa_coords);
        let skrifa_size = Size::new(params.font_size);
        let hinting_options = HintingOptions::default();
        let outline_glyphs = font_ref.outline_glyphs();
        let hinting_instance =
            HintingInstance::new(&outline_glyphs, skrifa_size, location_ref, hinting_options)?;
        self.skrifa_data = Some(SkrifaData {
            outline_glyphs,
            hinting_instance,
        });
        Ok(self
            .skrifa_data
            .as_ref()
            .expect("unable to store skrifa_data"))
    }

I'm not too worried about it, but it does smell of a pattern I'm missing, some kind of "fn insert_or_error(&mut Option, F: f) -> Result<&T, E>" function but I'm not sure how well that would work at it would have to borrow &mut self for the &mut Option then call the f which would capture self.

Option::insert will return you a reference, so no need to expect:

        Ok(self
            .skrifa_data
            .insert(SkrifaData { outline_glyphs, hinting_instance }))

Oh thanks! :slight_smile: