makepad-draw 1.0.0

Makepad 2d drawing API
Documentation
use {
    super::{
        font::FontId,
        font_family::FontFamilyId,
        layouter::{self, LaidoutText, LayoutParams, Layouter},
        loader::{FontDefinition, FontFamilyDefinition},
        rasterizer::Rasterizer,
    },
    makepad_platform::*,
    std::{cell::RefCell, mem, rc::Rc},
};

#[derive(Debug)]
pub struct Fonts {
    layouter: Layouter,
    needs_prepare_atlases: bool,
    grayscale_texture: Texture,
    color_texture: Texture,
}

impl Fonts {
    pub fn new(cx: &mut Cx, settings: layouter::Settings) -> Self {
        let layouter = Layouter::new(settings);
        let rasterizer = layouter.rasterizer().borrow();
        let grayscale_atlas_size = rasterizer.grayscale_atlas().size();
        let color_atlas_size = rasterizer.color_atlas().size();
        drop(rasterizer);
        Self {
            layouter,
            needs_prepare_atlases: false,
            grayscale_texture: Texture::new_with_format(
                cx,
                TextureFormat::VecRu8 {
                    width: grayscale_atlas_size.width,
                    height: grayscale_atlas_size.height,
                    data: None,
                    unpack_row_length: None,
                    updated: TextureUpdated::Empty,
                },
            ),
            color_texture: Texture::new_with_format(
                cx,
                TextureFormat::VecBGRAu8_32 {
                    width: color_atlas_size.width,
                    height: color_atlas_size.height,
                    data: None,
                    updated: TextureUpdated::Empty,
                },
            ),
        }
    }

    pub fn rasterizer(&self) -> &Rc<RefCell<Rasterizer>> {
        self.layouter.rasterizer()
    }

    pub fn grayscale_texture(&self) -> &Texture {
        &self.grayscale_texture
    }

    pub fn color_texture(&self) -> &Texture {
        &self.color_texture
    }

    pub fn is_font_family_known(&self, id: FontFamilyId) -> bool {
        self.layouter.is_font_family_known(id)
    }

    pub fn is_font_known(&self, id: FontId) -> bool {
        self.layouter.is_font_known(id)
    }

    pub fn define_font_family(&mut self, id: FontFamilyId, definition: FontFamilyDefinition) {
        self.layouter.define_font_family(id, definition);
    }

    pub fn define_font(&mut self, id: FontId, definition: FontDefinition) {
        self.layouter.define_font(id, definition);
    }

    pub fn get_or_layout(&mut self, params: impl LayoutParams) -> Rc<LaidoutText> {
        self.layouter.get_or_layout(params)
    }

    pub fn prepare_textures(&mut self, cx: &mut Cx) -> bool {
        assert!(!self.needs_prepare_atlases);
        let mut rasterizer = self.layouter.rasterizer().borrow_mut();
        if rasterizer.grayscale_atlas_mut().reset_if_needed() {
            return false;
        }
        if rasterizer.color_atlas_mut().reset_if_needed() {
            return false;
        }
        drop(rasterizer);
        self.prepare_grayscale_texture(cx);
        self.prepare_color_texture(cx);
        self.needs_prepare_atlases = true;
        true
    }

    fn prepare_grayscale_texture(&mut self, cx: &mut Cx) {
        let mut rasterizer = self.layouter.rasterizer().borrow_mut();
        let dirty_rect = rasterizer.grayscale_atlas_mut().take_dirty_image().bounds();
        let pixels: Vec<u8> = unsafe {
            mem::transmute(rasterizer.grayscale_atlas_mut().replace_pixels(Vec::new()))
        };
        self.grayscale_texture.put_back_vec_u8(
            cx,
            pixels,
            Some(RectUsize::new(
                PointUsize::new(dirty_rect.origin.x, dirty_rect.origin.y),
                SizeUsize::new(dirty_rect.size.width, dirty_rect.size.height),
            )),
        );
    }

    fn prepare_color_texture(&mut self, cx: &mut Cx) {
        let mut rasterizer = self.layouter.rasterizer().borrow_mut();
        let dirty_rect = rasterizer.color_atlas_mut().take_dirty_image().bounds();
        let pixels: Vec<u32> = unsafe {
            mem::transmute(rasterizer.color_atlas_mut().replace_pixels(Vec::new()))
        };
        self.color_texture.put_back_vec_u32(
            cx,
            pixels,
            Some(RectUsize::new(
                PointUsize::new(dirty_rect.origin.x, dirty_rect.origin.y),
                SizeUsize::new(dirty_rect.size.width, dirty_rect.size.height),
            )),
        )
    }

    pub fn prepare_atlases_if_needed(&mut self, cx: &mut Cx) {
        if !self.needs_prepare_atlases {
            return;
        }
        self.prepare_grayscale_atlas(cx);
        self.prepare_color_atlas(cx);
        self.needs_prepare_atlases = false;
    }

    fn prepare_grayscale_atlas(&mut self, cx: &mut Cx) {
        let mut rasterizer = self.layouter.rasterizer().borrow_mut();
        let pixels = self.grayscale_texture.take_vec_u8(cx);
        unsafe {
            rasterizer.grayscale_atlas_mut().replace_pixels(mem::transmute(pixels))
        };
    }

    fn prepare_color_atlas(&mut self, cx: &mut Cx) {
        let mut rasterizer = self.layouter.rasterizer().borrow_mut();
        let pixels = self.color_texture.take_vec_u32(cx);
        unsafe {
            rasterizer.color_atlas_mut().replace_pixels(mem::transmute(pixels))
        };
    }
}