FB2D - Estrutura 2D para Linux Frame Buffer (Rust)

Então eu decidi contar sobre a biblioteca que escrevi recentemente. Talvez alguém venha a calhar.
Esta é uma estrutura Rust 2D para renderização diretamente no Linux Frame Buffer / dev / fb0.


A tarefa era exibir cenas 2D simples na tela / TV no Raspberry Pi. O Raspberry Pi roda sob o controle do compilado com o Linux sem cabeça personalizado YoctoProject. Os gerenciadores de janelas estão ausentes, assim como o OpenGL. Somente o buffer de quadro permanece.


No caso do Frame Buffer, cada pixel deve ser processado. Como eu escrevo principalmente para o GoLang para Raspberry Pi, decidi escrever uma biblioteca no Go. Eu rapidamente percebi que o Go não era adequado para o meu desempenho. Ele não pôde realizar operações maciças com memória em um tempo razoável.


Então notei o Rust, que realizou testes semelhantes muito mais rapidamente.


Portanto, a biblioteca é desenvolvida no Rust. Como este é meu primeiro projeto em Rust, não chute muito, mas comentários são bem-vindos.


Como em qualquer biblioteca 2D, existem três entidades principais: cenas, nós e sprites.
Uma cena é um contêiner para objetos visuais. Um nó é um objeto virtual dotado de certas propriedades, como localização, tamanho etc. Nós podem ser aninhados.
Cada nó contém um objeto visual, o chamado sprite. Sprites vêm em várias formas. Sprites como RectSprite, TextureSprite, TextSprite agora são suportados.


RectSprite - um retângulo de uma determinada cor. O RectSprite incolor é normalmente usado para agrupar outros nós filhos. RectSprite corresponde à marca XML < caixa >


TextureSprite - um objeto para renderizar uma imagem. Atualmente, apenas PNG (RGBA) é suportado. TextureSprite corresponde à marca XML < image >


TechSprite - um objeto para renderizar uma linha de texto na fonte e no tamanho selecionados. Há suporte automático para RTL. TechSprite corresponde à marca XML < text >


Além dos atributos de localização e tamanho, cada nó possui atributos de gravidade e âncora. Isso ajuda a posicionar com precisão o objeto dentro de outro objeto. Todos os atributos relacionados ao tamanho e local são definidos como uma porcentagem do nó pai. Essa abordagem permite obter o melhor dimensionamento em telas de diferentes tamanhos e proporções.


É possível criar uma cena, programaticamente, ou criar um arquivo xml descrevendo a cena.


  1. Uma maneira de criar e executar uma cena.


    let mut fb = fb2d::screen_writer_for_framebuffer("/dev/fb0")?; fb2d::set_graphics_mode(); let mut scene = fb2d::scene::Scene::new(); let background_sprite = RectSprite::new(); let background_node = Node::new_rect_node(FLOAT_RECT_FULL, background_sprite); let sprite1 = RectSprite::new(); let mut node1 = Node::new_rect_node( FloatRect { pos: FLOAT_POS_ZERO, size: FLOAT_SIZE_HALF, }, sprite1, ); node1.anchor_point = ANCHOR_POINT_TOP_LEFT; let sprite2 = TextureSprite::new_for_texture("image.png"); let mut node2 = Node::new_texture_node( FloatRect { pos: FLOAT_POS_ZERO, size: FloatSize { width: 0.7, height: 0.7, }, }, sprite2, ); node2.anchor_point = ANCHOR_POINT_CENTER; let mut sprite3 = TextSprite::new(); sprite3.text = String::from("Hello, World !!!"); sprite3.gravity = GRAVITY_CENTER; sprite3.height = 0.2; let node3 = Node::new_text_node( FloatRect { pos: FLOAT_POS_ZERO, size: FLOAT_SIZE_FULL, }, sprite3, ); scene.add_node(node2, node1.key); scene.add_node(node1, background_node.key); scene.add_node(node3, background_node.key); scene.set_root_node(background_node); scene.writer = Some(Box::new(fb)); scene.run(); 

  2. Criando uma cena usando um arquivo XML.

 <scene color="#ffa500"> <box pos="0" size="95% 95%" anchor-point="0.5 0" color="#F0C0C0C0"> <text pos="0 -40%" size="100% 10%" anchor-point="0.5 0" height="100%" text="שלום Hello " font="Times New Roman.ttf" color="red"/> </box> <box pos="0%" size="25% 25%" anchor-point="0 1" color="olive" alpha="0.5"> <image pos="0" size="100% 100%" anchor-point="0 1" image="image1.png" /> </box> </scene> 

Uma cena é criada apontando para um diretório ou arquivo zip que contém scene.xml. Os arquivos de imagem e fonte dependentes devem estar localizados nesse diretório ou arquivo zip.


  match fb2d::scene::Scene::new_from_bundle("assets/scene1") { Ok(mut scene) => { let mut fb = fb2d::screen_writer_for_framebuffer("/dev/fb0")?; fb2d::set_graphics_mode(); scene.writer = Some(Box::new(fb)); scene.run(); } Err(e) => eprintln!("Error: {:?}", e), } 

Um exemplo da imagem resultante.
É possível renderizar um quadro em um arquivo PNG para depuração.



Repositório do GitHub.


Qualquer ajuda (contribuição) é apreciada. Há muito trabalho para otimizar a renderização e adicionar novos recursos, como animação.

Source: https://habr.com/ru/post/pt421707/


All Articles