mirui 0.37.0

A lightweight, no_std ECS-driven UI framework for embedded, desktop, and WebAssembly
Documentation
use super::SwRenderer;
use super::blit_fast::{blit_1to1_fast, blit_2to2_fast, blit_composite_dda, blit_dda};
use crate::render::command::CompositeMode;
use crate::render::texture::Texture;
use crate::types::{Fixed, Point, Rect};

impl SwRenderer<'_> {
    #[allow(clippy::too_many_arguments)]
    pub(super) fn blit_inner(
        &mut self,
        src: &Texture,
        src_rect: &Rect,
        dst: Point,
        dst_size: Point,
        clip: &Rect,
        opa: u8,
        radius: Fixed,
        composite: CompositeMode,
    ) {
        let phys_dst = self.viewport.point_to_physical(dst);
        let phys_dst_size = self.viewport.point_to_physical(dst_size);
        let phys_clip = self.viewport.rect_to_physical(*clip);
        let phys_radius = radius * self.viewport.scale();
        let (sx0, sy0, sw, sh) = src_rect.to_px();
        // Negative clip x flowing through to the byte-offset math
        // (`dx0 as usize * 4`) wraps; clamp to target bounds first.
        let target_w = self.target.width as i32;
        let target_h = self.target.height as i32;
        let (raw_x0, raw_y0, raw_x1, raw_y1) = phys_clip.pixel_bounds();
        let clip_x0 = raw_x0.max(0);
        let clip_y0 = raw_y0.max(0);
        let clip_x1 = raw_x1.min(target_w);
        let clip_y1 = raw_y1.min(target_h);
        let dx0 = phys_dst.x.to_int();
        let dy0 = phys_dst.y.to_int();
        let dw = phys_dst_size.x.to_int();
        let dh = phys_dst_size.y.to_int();
        if dw <= 0 || dh <= 0 || sw == 0 || sh == 0 {
            return;
        }

        if opa == 0 {
            return;
        }

        let needs_composite_path =
            !matches!(composite, CompositeMode::SourceOver) || phys_radius != Fixed::ZERO;
        if needs_composite_path {
            blit_composite_dda(
                &mut self.target,
                src,
                sx0,
                sy0,
                sw,
                sh,
                dx0,
                dy0,
                dw,
                dh,
                clip_x0,
                clip_y0,
                clip_x1,
                clip_y1,
                opa,
                composite,
                phys_radius,
            );
            return;
        }

        // opa < 255 → bypass per-format fast paths and go through the
        // per-pixel DDA so the alpha gets folded into each blend; the
        // fast paths' memcpy-ish row copies have no per-pixel hook.
        if opa < 255 {
            blit_dda(
                &mut self.target,
                src,
                sx0,
                sy0,
                sw,
                sh,
                dx0,
                dy0,
                dw,
                dh,
                clip_x0,
                clip_y0,
                clip_x1,
                clip_y1,
                opa,
            );
            return;
        }

        let sw_i = sw as i32;
        let sh_i = sh as i32;
        // 1× → format-specialized 1to1 fast path; 2× → 2to2; arbitrary → DDA.
        #[allow(clippy::if_same_then_else)]
        if dw == sw_i && dh == sh_i {
            blit_1to1_fast(
                &mut self.target,
                src,
                sx0,
                sy0,
                sw,
                sh,
                dx0,
                dy0,
                clip_x0,
                clip_y0,
                clip_x1,
                clip_y1,
            );
        } else if dw == sw_i * 2 && dh == sh_i * 2 {
            blit_2to2_fast(
                &mut self.target,
                src,
                sx0,
                sy0,
                sw,
                sh,
                dx0,
                dy0,
                clip_x0,
                clip_y0,
                clip_x1,
                clip_y1,
            );
        } else {
            blit_dda(
                &mut self.target,
                src,
                sx0,
                sy0,
                sw,
                sh,
                dx0,
                dy0,
                dw,
                dh,
                clip_x0,
                clip_y0,
                clip_x1,
                clip_y1,
                255,
            );
        }
    }
}