From 3faf1c7c8b58fe61c9d1bb276959f93f126c1570 Mon Sep 17 00:00:00 2001 From: bem130 Date: Mon, 22 Sep 2025 19:19:06 +0900 Subject: [PATCH 1/5] =?UTF-8?q?github=E3=81=AB=E3=83=AA=E3=83=AA=E3=83=BC?= =?UTF-8?q?=E3=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 198 ++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..8a5e1fa --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,198 @@ +name: Release and Deploy + +on: + push: + branches: + - master + +env: + APP_NAME: rust_multibackend_app + CARGO_TERM_COLOR: always + +jobs: + build-binaries: + name: Build Binaries + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + use-cross: false + ext: "" + - os: ubuntu-latest + target: aarch64-unknown-linux-gnu + use-cross: true + ext: "" + - os: ubuntu-latest + target: riscv64gc-unknown-linux-gnu + use-cross: true + ext: "" + - os: macos-latest + target: x86_64-apple-darwin + use-cross: false + ext: "" + - os: macos-latest + target: aarch64-apple-darwin + use-cross: false + ext: "" + - os: windows-latest + target: x86_64-pc-windows-msvc + use-cross: false + ext: ".exe" + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{ matrix.target }} + override: true + profile: minimal + + - name: Install cross + if: matrix.use-cross == true + run: cargo install cross --git https://github.com/cross-rs/cross --branch main + + - name: Build TUI + uses: actions-rs/cargo@v1 + with: + use-cross: ${{ matrix.use-cross }} + command: build + args: --release --no-default-features --features tui --target ${{ matrix.target }} + + - name: Rename TUI artifact + shell: bash + run: | + mv target/${{ matrix.target }}/release/${{ env.APP_NAME }}${{ matrix.ext }} ./tui-artifact${{ matrix.ext }} + + - name: Build GUI + uses: actions-rs/cargo@v1 + with: + use-cross: ${{ matrix.use-cross }} + command: build + args: --release --no-default-features --features gui --target ${{ matrix.target }} + + - name: Rename GUI artifact + shell: bash + run: | + mv target/${{ matrix.target }}/release/${{ env.APP_NAME }}${{ matrix.ext }} ./gui-artifact${{ matrix.ext }} + + - name: Upload Binaries + uses: actions/upload-artifact@v4 + with: + name: binaries-${{ matrix.target }} + path: | + ./tui-artifact${{ matrix.ext }} + ./gui-artifact${{ matrix.ext }} + + build-uefi: + name: Build UEFI + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: x86_64-unknown-uefi + override: true + components: rust-src + - name: Build UEFI binary + run: cargo build --release --target x86_64-unknown-uefi --no-default-features --features uefi + - name: Upload UEFI artifact + uses: actions/upload-artifact@v4 + with: + name: uefi-binary + path: target/x86_64-unknown-uefi/release/${{ env.APP_NAME }}.efi + + build-wasm: + name: Build WASM + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + - name: Install wasm-pack + run: cargo install wasm-pack + - name: Build WASM package + run: wasm-pack build --target web -- --no-default-features --features wasm + - name: Prepare Pages directory + run: | + mkdir dist + cp pkg/rust_multibackend_app_bg.wasm dist/ + cp pkg/rust_multibackend_app.js dist/ + cp index.html dist/ + sed -i 's|./pkg/rust_multibackend_app.js|./rust_multibackend_app.js|' dist/index.html + - name: Upload WASM artifact + uses: actions/upload-artifact@v4 + with: + name: pages-artifact + path: dist + + release: + name: Create Release + needs: [build-binaries, build-uefi] + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Get release version + id: get_version + run: echo "version=v$(date +'%Y%m%d.%H%M%S')" >> $GITHUB_ENV + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + - name: Organize files + run: | + mkdir release-files + find artifacts -type f -name "tui-artifact*" | while read -r file; do + target_name=$(basename "$(dirname "$file")" | sed 's/binaries-//') + ext=$(echo "$file" | grep -oE '\.[^.]*$|' | sed 's/\.//') + mv "$file" "release-files/${{ env.APP_NAME }}-tui-${target_name}${ext}" + done + find artifacts -type f -name "gui-artifact*" | while read -r file; do + target_name=$(basename "$(dirname "$file")" | sed 's/binaries-//') + ext=$(echo "$file" | grep -oE '\.[^.]*$|' | sed 's/\.//') + mv "$file" "release-files/${{ env.APP_NAME }}-gui-${target_name}${ext}" + done + mv artifacts/uefi-binary/${{ env.APP_NAME }}.efi release-files/ + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ env.version }} + name: Release ${{ env.version }} + files: release-files/* + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + deploy-pages: + name: Deploy to GitHub Pages + needs: build-wasm + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + steps: + - name: Download WASM artifact + uses: actions/download-artifact@v4 + with: + name: pages-artifact + path: ./dist + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./dist + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 \ No newline at end of file From 23cbd184e475856ccafe9ba41ea99e8400a74158 Mon Sep 17 00:00:00 2001 From: bem130 Date: Mon, 22 Sep 2025 19:29:48 +0900 Subject: [PATCH 2/5] =?UTF-8?q?deploy=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a5e1fa..e914a34 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -179,20 +179,15 @@ jobs: needs: build-wasm runs-on: ubuntu-latest permissions: - pages: write - id-token: write + contents: write steps: - name: Download WASM artifact uses: actions/download-artifact@v4 with: name: pages-artifact path: ./dist - - name: Setup Pages - uses: actions/configure-pages@v4 - - name: Upload Pages artifact - uses: actions/upload-pages-artifact@v3 - with: - path: ./dist - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 \ No newline at end of file + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./dist \ No newline at end of file From d76bed5b1d936c0c7e8fbde3850b22e57d767796 Mon Sep 17 00:00:00 2001 From: bem130 Date: Mon, 22 Sep 2025 19:40:07 +0900 Subject: [PATCH 3/5] =?UTF-8?q?=E3=81=84=E3=82=8D=E3=81=84=E3=82=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 3 ++- .gitignore | 3 ++- readme.md | 4 ++-- src/gui.rs | 6 +++--- uefi_image/EFI/BOOT/BOOTX64.EFI | Bin 8446464 -> 8446464 bytes 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e914a34..4ed2cc7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -190,4 +190,5 @@ jobs: uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./dist \ No newline at end of file + publish_dir: ./dist + force_orphan: true \ No newline at end of file diff --git a/.gitignore b/.gitignore index 510e99a..fcf26ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target /pkg -/src.txt \ No newline at end of file +/src.txt +*/*.EFI \ No newline at end of file diff --git a/readme.md b/readme.md index 275bc61..84e5f8d 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ -# Rust Multi-Backend App (GUI / TUI / WASM) +# Typing Multi-Platform app (GUI / EFI / TUI / WASM) -RustでGUI、TUI、WASMの3つのバックエンドを持つテキスト入力アプリケーションのサンプルです。 +RustでGUI、EFI、TUI、WASMの4つのバックエンドを持つテキスト入力アプリケーションのサンプルです。 ## 実行方法 diff --git a/src/gui.rs b/src/gui.rs index cb25092..e15693c 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -8,7 +8,6 @@ use minifb::{Key, KeyRepeat, Window, WindowOptions}; const WIDTH: usize = 800; const HEIGHT: usize = 300; -const BIG_FONT_SIZE: f32 = 48.0; const NORMAL_FONT_SIZE: f32 = 16.0; /// GUIアプリケーションのメイン関数 @@ -19,6 +18,7 @@ pub fn run() -> Result<(), Box> { let mut window = Window::new("GUI Text Input", WIDTH, HEIGHT, WindowOptions::default())?; window.set_target_fps(60); let mut app = App::new(); + let big_font_size = HEIGHT as f32 * 0.5; // メインループ while window.is_open() && !app.should_quit { @@ -34,12 +34,12 @@ pub fn run() -> Result<(), Box> { for item in render_list { match item { Renderable::BigText { text, anchor, shift, align } => { - let (text_width, text_height) = gui_renderer::measure_text(&font, text, BIG_FONT_SIZE); + let (text_width, text_height) = gui_renderer::measure_text(&font, text, big_font_size); let anchor_pos = ui::calculate_anchor_position(anchor, shift, WIDTH, HEIGHT); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( &mut pixel_buffer, WIDTH, &font, text, - (x as f32, y as f32), BIG_FONT_SIZE, + (x as f32, y as f32), big_font_size, ); } Renderable::Text { text, anchor, shift, align } => { diff --git a/uefi_image/EFI/BOOT/BOOTX64.EFI b/uefi_image/EFI/BOOT/BOOTX64.EFI index a95a3a7abf9bbfed34c3ded57797e8dfd8d4d27a..8031f730ba46a85b19e16b9734159e5a2ec576b5 100644 GIT binary patch delta 444 zcmWN==`xi80D$4+WJw26M2R9orIaOdqOxWwoU|eBmK;h+);@3Z{&xvY_t4Y@xB!3R z3iQ(*m~oz&C)oOt93*ZA;rQMLk|bd{BFT~>sgfo~C0&k5L^32(vgEjAOOBk7laecW za!T^0Ku*gUDU`EPB*k)0&P$1u$^|Kta=9oKQYlq(NiNG3sg|p9O={%2+>lzSlX_{8 zo6;yva!Z;eDz~LYTIG)1m3z`A?b0Eg(k0z;UwWih`lMeT$U_;BK^c;mJd$B~EKlUA zJd@`#BBL@UFJxR^$}4#-Z{)4KllL+qlQJdK@kjz(fX50?LQ?*xA%hhJm6 Ab^rhX delta 444 zcmWN=**4Sx0KnlfDAGzw3l&PTrG?Z)m~0g?wiY|lLPIJP{rx(>d(WU}=+uqVja%oq zX&%6Z=P=(nU$Ff%ElA!7!tuRzBt^oKDru4~hvcwiNTwW-EIBI229maB42O60nf$_*)#a;cC?sgj#gEw|*h+>yId zBeil*>g2vWkcd2#dTEeH(kM;REKzwZEz&A&(k>nHM4rks>69+%mgmwVG3k{)>6ZZ+ zlo#?+Udd}2l3^K**o{AEfM_9IsjXH By5Rr- From e5e7948471d3926f8d72d7a50deca9af407994a1 Mon Sep 17 00:00:00 2001 From: bem130 Date: Mon, 22 Sep 2025 19:47:36 +0900 Subject: [PATCH 4/5] =?UTF-8?q?=E3=82=A6=E3=82=A4=E3=83=B3=E3=83=89?= =?UTF-8?q?=E3=82=A6=E3=83=AA=E3=82=B5=E3=82=A4=E3=82=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gui.rs | 36 +++++++++---- src/uefi.rs | 9 ++-- src/wasm.rs | 92 ++++++++++++++++++++++++-------- uefi_image/EFI/BOOT/BOOTX64.EFI | Bin 8446464 -> 8446464 bytes 4 files changed, 100 insertions(+), 37 deletions(-) diff --git a/src/gui.rs b/src/gui.rs index e15693c..3e38867 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -6,8 +6,6 @@ use crate::ui::{self, Renderable}; use ab_glyph::FontRef; use minifb::{Key, KeyRepeat, Window, WindowOptions}; -const WIDTH: usize = 800; -const HEIGHT: usize = 300; const NORMAL_FONT_SIZE: f32 = 16.0; /// GUIアプリケーションのメイン関数 @@ -15,17 +13,35 @@ pub fn run() -> Result<(), Box> { let font_data = include_bytes!("../fonts/NotoSerifJP-Regular.ttf"); let font = FontRef::try_from_slice(font_data).map_err(|_| "Failed to load font from slice")?; - let mut window = Window::new("GUI Text Input", WIDTH, HEIGHT, WindowOptions::default())?; + let mut width = 800; + let mut height = 300; + + let mut window = Window::new( + "GUI Text Input", + width, + height, + WindowOptions { + resize: true, + ..WindowOptions::default() + }, + )?; window.set_target_fps(60); let mut app = App::new(); - let big_font_size = HEIGHT as f32 * 0.5; + let mut big_font_size = height as f32 * 0.5; // メインループ while window.is_open() && !app.should_quit { + let (new_width, new_height) = window.get_size(); + if new_width != width || new_height != height { + width = new_width; + height = new_height; + big_font_size = height as f32 * 0.5; + } + handle_input(&mut window, &mut app); // 1. 背景色でピクセルバッファをクリア - let mut pixel_buffer = vec![BG_COLOR; WIDTH * HEIGHT]; + let mut pixel_buffer = vec![BG_COLOR; width * height]; // 2. UI定義から描画リストを取得 let render_list = ui::build_ui(&app); @@ -35,19 +51,19 @@ pub fn run() -> Result<(), Box> { match item { Renderable::BigText { text, anchor, shift, align } => { let (text_width, text_height) = gui_renderer::measure_text(&font, text, big_font_size); - let anchor_pos = ui::calculate_anchor_position(anchor, shift, WIDTH, HEIGHT); + let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( - &mut pixel_buffer, WIDTH, &font, text, + &mut pixel_buffer, width, &font, text, (x as f32, y as f32), big_font_size, ); } Renderable::Text { text, anchor, shift, align } => { let (text_width, text_height) = gui_renderer::measure_text(&font, text, NORMAL_FONT_SIZE); - let anchor_pos = ui::calculate_anchor_position(anchor, shift, WIDTH, HEIGHT); + let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( - &mut pixel_buffer, WIDTH, &font, text, + &mut pixel_buffer, width, &font, text, (x as f32, y as f32), NORMAL_FONT_SIZE, ); } @@ -55,7 +71,7 @@ pub fn run() -> Result<(), Box> { } // 4. 完成したバッファをウィンドウに表示 - window.update_with_buffer(&pixel_buffer, WIDTH, HEIGHT)?; + window.update_with_buffer(&pixel_buffer, width, height)?; } Ok(()) } diff --git a/src/uefi.rs b/src/uefi.rs index 7d98726..16bfaa5 100644 --- a/src/uefi.rs +++ b/src/uefi.rs @@ -12,10 +12,8 @@ use crate::ui::{self, Renderable}; use ab_glyph::{Font, FontRef, point, OutlinedGlyph, PxScale, ScaleFont}; use alloc::vec::Vec; -const BIG_FONT_SIZE: f32 = 48.0; const NORMAL_FONT_SIZE: f32 = 16.0; - pub fn run() -> Status { uefi::helpers::init().unwrap(); @@ -26,6 +24,7 @@ pub fn run() -> Status { // Get current mode info let mode_info = gop.current_mode_info(); let (width, height) = mode_info.resolution(); + let big_font_size = height as f32 * 0.5; // Load font let font_data: &[u8] = include_bytes!("../fonts/NotoSerifJP-Regular.ttf"); @@ -78,12 +77,12 @@ pub fn run() -> Status { for item in render_list { match item { Renderable::BigText { text, anchor, shift, align } => { - let (text_width, text_height) = measure_text(&font, text, BIG_FONT_SIZE); + let (text_width, text_height) = measure_text(&font, text, big_font_size); let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); draw_text( &mut pixel_buffer, width, &font, text, - (x as f32, y as f32), BIG_FONT_SIZE, + (x as f32, y as f32), big_font_size, ); } Renderable::Text { text, anchor, shift, align } => { @@ -181,4 +180,4 @@ fn measure_text(font: &FontRef, text: &str, size: f32) -> (u32, u32) { last_glyph_id = Some(glyph); } (total_width as u32, max_height as u32) -} \ No newline at end of file +} diff --git a/src/wasm.rs b/src/wasm.rs index 0cf5cc5..0733878 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -8,9 +8,6 @@ use wasm_bindgen::prelude::*; use wasm_bindgen::Clamped; use web_sys::{CanvasRenderingContext2d, ImageData, KeyboardEvent}; -const WIDTH: usize = 800; -const HEIGHT: usize = 100; -const BIG_FONT_SIZE: f32 = 48.0; const NORMAL_FONT_SIZE: f32 = 16.0; /// WASMモジュールのエントリーポイント @@ -21,17 +18,45 @@ pub fn start() -> Result<(), JsValue> { let document = window.document().unwrap(); let body = document.body().unwrap(); - let canvas = document.create_element("canvas")?.dyn_into::()?; - canvas.set_width(WIDTH as u32); - canvas.set_height(HEIGHT as u32); + let canvas = document + .create_element("canvas")? + .dyn_into::()?; body.append_child(&canvas)?; - let context = canvas.get_context("2d")?.unwrap().dyn_into::()?; + let context = + canvas.get_context("2d")?.unwrap().dyn_into::()?; let font = FontRef::try_from_slice(include_bytes!("../fonts/NotoSerifJP-Regular.ttf")) .map_err(|e| JsValue::from_str(&e.to_string()))?; let app = Rc::new(RefCell::new(App::new())); + let size = Rc::new(RefCell::new((0, 0))); + + // 初期サイズ設定とリサイズハンドラ + { + let window_clone = window.clone(); + let canvas_clone = canvas.clone(); + let size_clone = size.clone(); + let resize_handler = Closure::::new(move || { + let width = window_clone.inner_width().unwrap().as_f64().unwrap() as u32; + let height = window_clone.inner_height().unwrap().as_f64().unwrap() as u32; + canvas_clone.set_width(width); + canvas_clone.set_height(height); + *size_clone.borrow_mut() = (width as usize, height as usize); + }); + window.add_event_listener_with_callback("resize", resize_handler.as_ref().unchecked_ref())?; + resize_handler.forget(); + // 初期サイズを設定するために一度呼び出す + let window_clone = window.clone(); + let canvas_clone = canvas.clone(); + let size_clone = size.clone(); + let width = window_clone.inner_width().unwrap().as_f64().unwrap() as u32; + let height = window_clone.inner_height().unwrap().as_f64().unwrap() as u32; + canvas_clone.set_width(width); + canvas_clone.set_height(height); + *size_clone.borrow_mut() = (width as usize, height as usize); + } + // キーボードイベントのリスナーを設定 { let app_clone = app.clone(); @@ -52,10 +77,12 @@ pub fn start() -> Result<(), JsValue> { let f = Rc::new(RefCell::new(None)); let g = f.clone(); *g.borrow_mut() = Some(Closure::::new(move || { + let (width, height) = *size.borrow(); + let big_font_size = height as f32 * 0.5; let app = app.borrow(); // 描画中は不変借用 // 1. 背景色でピクセルバッファをクリア - let mut pixel_buffer = vec![BG_COLOR; WIDTH * HEIGHT]; + let mut pixel_buffer = vec![BG_COLOR; width * height]; // 2. UI定義から描画リストを取得 let render_list = ui::build_ui(&app); @@ -63,33 +90,51 @@ pub fn start() -> Result<(), JsValue> { // 3. 描画リストを解釈して描画 for item in render_list { match item { - Renderable::BigText { text, anchor, shift, align } => { - let (text_width, text_height) = gui_renderer::measure_text(&font, text, BIG_FONT_SIZE); - let anchor_pos = ui::calculate_anchor_position(anchor, shift, WIDTH, HEIGHT); + Renderable::BigText { text, anchor, shift, align } => { + let (text_width, text_height) = gui_renderer::measure_text(&font, text, big_font_size); + let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( - &mut pixel_buffer, WIDTH, &font, text, - (x as f32, y as f32), BIG_FONT_SIZE, + &mut pixel_buffer, + width, + &font, + text, + (x as f32, y as f32), + big_font_size, ); } Renderable::Text { text, anchor, shift, align } => { let (text_width, text_height) = gui_renderer::measure_text(&font, text, NORMAL_FONT_SIZE); - let anchor_pos = ui::calculate_anchor_position(anchor, shift, WIDTH, HEIGHT); + let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( - &mut pixel_buffer, WIDTH, &font, text, - (x as f32, y as f32), NORMAL_FONT_SIZE, + &mut pixel_buffer, + width, + &font, + text, + (x as f32, y as f32), + NORMAL_FONT_SIZE, ); } } } - + // 4. 完成したバッファをCanvasに転送 - let mut u8_buffer = Vec::with_capacity(WIDTH * HEIGHT * 4); + let mut u8_buffer = Vec::with_capacity(width * height * 4); for pixel in pixel_buffer.iter() { - u8_buffer.extend_from_slice(&[((*pixel >> 16) & 0xFF) as u8, ((*pixel >> 8) & 0xFF) as u8, (*pixel & 0xFF) as u8, 255]); + u8_buffer.extend_from_slice(&[ + ((*pixel >> 16) & 0xFF) as u8, + ((*pixel >> 8) & 0xFF) as u8, + (*pixel & 0xFF) as u8, + 255, + ]); } - let image_data = ImageData::new_with_u8_clamped_array_and_sh(Clamped(&u8_buffer), WIDTH as u32, HEIGHT as u32).unwrap(); + let image_data = ImageData::new_with_u8_clamped_array_and_sh( + Clamped(&u8_buffer), + width as u32, + height as u32, + ) + .unwrap(); context.put_image_data(&image_data, 0.0, 0.0).unwrap(); // 次のフレームを要求 @@ -102,5 +147,8 @@ pub fn start() -> Result<(), JsValue> { /// requestAnimationFrameを呼び出すヘルパー関数 fn request_animation_frame(f: &Closure) { - web_sys::window().unwrap().request_animation_frame(f.as_ref().unchecked_ref()).unwrap(); -} \ No newline at end of file + web_sys::window() + .unwrap() + .request_animation_frame(f.as_ref().unchecked_ref()) + .unwrap(); +} diff --git a/uefi_image/EFI/BOOT/BOOTX64.EFI b/uefi_image/EFI/BOOT/BOOTX64.EFI index 8031f730ba46a85b19e16b9734159e5a2ec576b5..b517c17f2346901f69d4a6e16499864777cb303b 100644 GIT binary patch delta 44790 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≻Vf-wco(A$Dmn+$z*~7xX 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%0Ay~pc!A9%Gs-jp!FnsW>tun;> zdB%UIR@kR3wf7lxuPwOJoF-JGoswl&^XOP8y%CdQX7g7GGuwW`48m9H+9^pmKdRbZ z>ESVU>lc0L8%r2%@tDywVfFxD&&JbFqG^v&UVEjcG+tZS9#PPJbvi0_*`>3T-ci{E zf*90E>FLz+?AUTeMtJQNk3R|18>IGQMHa9|QBEhNsT4r(Iw=EjJm0;uGL~J%#kS7M zFx)0e?4q=!xMbX6KGQ|tOG0S~|v@B+L6AHWyz11bTP0e>I>2n2$FU?2pj0#pS;fiNH(hybbq)qxs7O&}78 z0%`%#Ky4rfr~||TaX?+59#9{M2O0nkfkr?A&=_a}GzFRg&4Cs`OQ02y2($*;07*bw zpdHX2=m2yCIsu)5ENWdFdP^Gj08pjqk%ENSYRA59+&|9ti6^xQNP&D*h|=ev~e}2g0k_|M0FwdFC2??Jq)$3pCq| zCSI}E=nH`;2aP@fSO>_C8oeFR3m6WZ1FAY{^mT!Gz$%~^=+Ll)xOYYu z6duS2E&?wB(`1d_4~PLeB#Q_gXhs*!ZRXjD`Xy`J?Q)+Q@(sOjFmr`T=N&X{wQu0h zSh@M2A{x9Zih%BUO_lF<=&AUxW=-86$_xd=lXQSfB#`@x!h zOe)ak4byCtq&RKI;hL$uLP3Th%-vG6TqeC4t@#k`@miw~1JZ%Hz%!uZ8;mnx0&oTh zeyh=M0v-cC?=<>kfZl27o>bnB&MnaN)GiyVDXuVa{;G8S4&V~-4p3I7>;L*KU4Ia8 z)f&t}rDj2?Sz(XC-KW$X0rLo8m7lKnzJl~FrR!Ujn&SWefr<{}Ja1?3aFUGr5Y20abx|SGyTX*A|xV8KnL2e;ocd2JT-hL!bY!|LFJq z|5${X4TzDMn^N9!UZ{yWzOp*(0duI*mFuzpsgN zXtfCTiy_#aY)z=NNGmPSY`3v|ux^sR+xkg*3!vtD?ZFM23X=8r$MSy4N6u3@Hx3LpHw(}r?;N(XPLX`OGdTkkD(-)ER04)a14?W-KkRcrgA1{wMf zfYdNUZw@#B-VL?4^EJbmn|W%6zA2CicKRd~p#7cUF?JpnPJc-VUI9gEXD#)^Lr9cJ3KXwz2Pg|MO|0yKsG>Tz#PSV@Dw~24F x>MQ@$^nLlt+JwuRa}v)jFRP@?K^u45%tfNOwDLO^Ue|cCX_d9!*EP3|{vS(AxN!gg delta 44859 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 EAG*z|e*gdg From a5eef4fdabf639279197c5436812cbb4dd078eb6 Mon Sep 17 00:00:00 2001 From: bem130 Date: Mon, 22 Sep 2025 20:12:42 +0900 Subject: [PATCH 5/5] =?UTF-8?q?=E3=83=AC=E3=82=A4=E3=82=A2=E3=82=A6?= =?UTF-8?q?=E3=83=88=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src.txt | 476 +++++++++++++++++++++++--------- src/gui.rs | 6 +- src/renderer.rs | 46 +-- src/uefi.rs | 23 +- src/wasm.rs | 6 +- uefi_image/EFI/BOOT/BOOTX64.EFI | Bin 8446464 -> 8446464 bytes 6 files changed, 387 insertions(+), 170 deletions(-) diff --git a/src.txt b/src.txt index 2c42ff2..511dc95 100644 --- a/src.txt +++ b/src.txt @@ -55,29 +55,45 @@ impl App { use crate::app::App; use crate::renderer::{gui_renderer, BG_COLOR}; use crate::ui::{self, Renderable}; -use ab_glyph::{Font, FontRef}; +use ab_glyph::FontRef; use minifb::{Key, KeyRepeat, Window, WindowOptions}; -const WIDTH: usize = 800; -const HEIGHT: usize = 100; -const BIG_FONT_SIZE: f32 = 48.0; const NORMAL_FONT_SIZE: f32 = 16.0; /// GUIアプリケーションのメイン関数 pub fn run() -> Result<(), Box> { let font_data = include_bytes!("../fonts/NotoSerifJP-Regular.ttf"); - let font = FontRef::try_from_slice(font_data)?; - - let mut window = Window::new("GUI Text Input", WIDTH, HEIGHT, WindowOptions::default())?; - window.limit_update_rate(Some(std::time::Duration::from_micros(16600))); + let font = FontRef::try_from_slice(font_data).map_err(|_| "Failed to load font from slice")?; + + let mut width = 800; + let mut height = 300; + + let mut window = Window::new( + "GUI Text Input", + width, + height, + WindowOptions { + resize: true, + ..WindowOptions::default() + }, + )?; + window.set_target_fps(60); let mut app = App::new(); + let mut big_font_size = height as f32 * 0.5; // メインループ while window.is_open() && !app.should_quit { + let (new_width, new_height) = window.get_size(); + if new_width != width || new_height != height { + width = new_width; + height = new_height; + big_font_size = height as f32 * 0.5; + } + handle_input(&mut window, &mut app); // 1. 背景色でピクセルバッファをクリア - let mut pixel_buffer = vec![BG_COLOR; WIDTH * HEIGHT]; + let mut pixel_buffer = vec![BG_COLOR; width * height]; // 2. UI定義から描画リストを取得 let render_list = ui::build_ui(&app); @@ -85,25 +101,29 @@ pub fn run() -> Result<(), Box> { // 3. 描画リストの各要素を解釈して描画 for item in render_list { match item { - Renderable::BigText { text, anchor, margin } => { - let pos = ui::calculate_position(anchor, margin, WIDTH, HEIGHT); + Renderable::BigText { text, anchor, shift, align } => { + let (text_width, text_height, _ascent) = gui_renderer::measure_text(&font, text, big_font_size); + let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); + let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( - &mut pixel_buffer, WIDTH, &font, text, - (pos.0 as f32, pos.1 as f32), BIG_FONT_SIZE, + &mut pixel_buffer, width, &font, text, + (x as f32, y as f32), big_font_size, ); } - Renderable::Text { text, anchor, margin } => { - let pos = ui::calculate_position(anchor, margin, WIDTH, HEIGHT); + Renderable::Text { text, anchor, shift, align } => { + let (text_width, text_height, ascent) = gui_renderer::measure_text(&font, text, NORMAL_FONT_SIZE); + let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); + let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( - &mut pixel_buffer, WIDTH, &font, text, - (pos.0 as f32, pos.1 as f32), NORMAL_FONT_SIZE, + &mut pixel_buffer, width, &font, text, + (x as f32, y as f32), NORMAL_FONT_SIZE, ); } } } // 4. 完成したバッファをウィンドウに表示 - window.update_with_buffer(&pixel_buffer, WIDTH, HEIGHT)?; + window.update_with_buffer(&pixel_buffer, width, height)?; } Ok(()) } @@ -176,6 +196,7 @@ fn key_to_char(key: Key, is_shift: bool) -> Option { _ => None, } } + --- ./src\lib.rs @@ -188,16 +209,6 @@ fn key_to_char(key: Key, is_shift: bool) -> Option { // uefi featureが有効な場合にのみ必要となる設定 #[cfg(feature = "uefi")] mod uefi_setup { - use core::panic::PanicInfo; - - /// no_std環境ではパニック時の処理を自分で定義する必要がある - #[panic_handler] - fn panic_handler(_info: &PanicInfo) -> ! { // FIX: info -> _info to suppress unused variable warning - // logクレートの初期化を行っていないため、ここでの呼び出しは削除します。 - // log::error!("[PANIC] {}", info); - loop {} - } - /// uefiクレートが提供するアロケータをグローバルアロケータとして設定 #[global_allocator] static ALLOCATOR: uefi::allocator::Allocator = uefi::allocator::Allocator; @@ -226,7 +237,11 @@ pub mod uefi; --- ./src\main.rs +#![cfg_attr(feature = "uefi", no_std)] +#![cfg_attr(feature = "uefi", no_main)] + /// main関数 - featureフラグに応じて各バックエンドを起動 +#[cfg(not(feature = "uefi"))] fn main() -> Result<(), Box> { // "gui" featureが有効な場合にコンパイルされるブロック #[cfg(feature = "gui")] @@ -239,7 +254,7 @@ fn main() -> Result<(), Box> { #[cfg(all(not(feature = "gui"), feature = "tui"))] { println!("Starting TUI version... (Press 'q' to exit)"); - std::thread::sleep(std::time::Duration::from_secs(2)); + // std::thread::sleep(std::time::Duration::from_secs(2)); return rust_multibackend_app::tui::run(); } @@ -250,6 +265,15 @@ fn main() -> Result<(), Box> { return Ok(()); } } + + +#[cfg(feature = "uefi")] +#[uefi::entry] + fn efi_main() -> uefi::prelude::Status { + // ここで `run` 関数を呼び出すか、`run` 関数の内容を直接記述します。 + // `run` 関数のシグネチャを合わせる必要があるかもしれません。 + rust_multibackend_app::uefi::run() +} --- ./src\renderer.rs @@ -268,7 +292,7 @@ use std::vec::Vec; #[cfg(feature = "uefi")] use core_maths::CoreFloat; -use ab_glyph::{point, Font, FontRef, OutlinedGlyph}; +use ab_glyph::{point, Font, FontRef, OutlinedGlyph, PxScale, ScaleFont}; /// テキストの描画色 pub const TEXT_COLOR: u32 = 0x00_FFFFFF; @@ -284,21 +308,29 @@ pub mod gui_renderer { buffer: &mut [u32], stride: usize, font: &FontRef, text: &str, pos: (f32, f32), font_size: f32, ) { - let scale = font_size / (font.ascent_unscaled() - font.descent_unscaled()); + let scale = PxScale::from(font_size); + let scaled_font = font.as_scaled(scale); + let ascent = scaled_font.ascent(); let mut pen_x = pos.0; - let pen_y = pos.1; + let pen_y = pos.1 + ascent; + let mut last_glyph = None; for character in text.chars() { - let glyph = font.glyph_id(character).with_scale_and_position(font_size, point(pen_x, pen_y)); + let glyph_id = font.glyph_id(character); + if let Some(last) = last_glyph { + pen_x += scaled_font.kern(last, glyph_id); + } + let glyph = glyph_id.with_scale_and_position(scale, point(pen_x, pen_y)); if let Some(outlined) = font.outline_glyph(glyph) { draw_glyph_to_pixel_buffer(buffer, stride, &outlined); } - pen_x += font.h_advance_unscaled(font.glyph_id(character)) * scale; + pen_x += scaled_font.h_advance(glyph_id); + last_glyph = Some(glyph_id); } } /// アウトライン化されたグリフをピクセルバッファに描画する(内部関数) - fn draw_glyph_to_pixel_buffer(buffer: &mut [u32], stride: usize, outlined: &OutlinedGlyph) { + fn draw_glyph_to_pixel_buffer(buffer: &mut [u32], stride: usize, outlined: &OutlinedGlyph) { let bounds = outlined.px_bounds(); outlined.draw(|x, y, c| { let buffer_x = bounds.min.x as i32 + x as i32; @@ -309,9 +341,9 @@ pub mod gui_renderer { let text_r = ((TEXT_COLOR >> 16) & 0xFF) as f32; let text_g = ((TEXT_COLOR >> 8) & 0xFF) as f32; let text_b = (TEXT_COLOR & 0xFF) as f32; - let bg_r = ((BG_COLOR >> 16) & 0xFF) as f32; - let bg_g = ((BG_COLOR >> 8) & 0xFF) as f32; - let bg_b = (BG_COLOR & 0xFF) as f32; + let bg_r = ((buffer[index] >> 16) & 0xFF) as f32; + let bg_g = ((buffer[index] >> 8) & 0xFF) as f32; + let bg_b = (buffer[index] & 0xFF) as f32; let r = (text_r * c + bg_r * (1.0 - c)) as u32; let g = (text_g * c + bg_g * (1.0 - c)) as u32; let b = (text_b * c + bg_b * (1.0 - c)) as u32; @@ -319,6 +351,28 @@ pub mod gui_renderer { } }); } + + /// テキストの描画サイズ(幅と高さ)を計算する + pub fn measure_text(font: &FontRef, text: &str, size: f32) -> (u32, u32, f32) { + let scale = PxScale::from(size); + let scaled_font = font.as_scaled(scale); + let mut total_width = 0.0; + + let mut last_glyph_id = None; + for c in text.chars() { + if c == '\n' { + continue; + } + let glyph = font.glyph_id(c); + if let Some(last_id) = last_glyph_id { + total_width += scaled_font.kern(last_id, glyph); + } + total_width += scaled_font.h_advance(glyph); + last_glyph_id = Some(glyph); + } + let height = scaled_font.ascent() - scaled_font.descent(); + (total_width as u32, height as u32, scaled_font.ascent()) + } } /// TUIバックエンド用の文字ベースレンダラ @@ -353,12 +407,21 @@ pub mod tui_renderer { if buffer_x < width && buffer_y < height { let index = buffer_y * width + buffer_x; let coverage_char = match (c * 4.0).round() as u8 { - 0 => ' ', 1 => '.', 2 => '*', 3 => '#', _ => '@', + 0 => ' ', + 1 => '.', + 2 => '*', + 3 => '#', + _ => '@', }; if buffer[index] == ' ' { buffer[index] = coverage_char; } } }); } + + /// テキストの描画サイズ(幅と高さ)を計算する + pub fn measure_text(text: &str) -> (u32, u32) { + (text.chars().count() as u32, 1) + } } --- @@ -366,7 +429,7 @@ pub mod tui_renderer { use crate::app::App; use crate::renderer::tui_renderer; use crate::ui::{self, Renderable}; -use ab_glyph::{Font, FontRef}; +use ab_glyph::FontRef; use crossterm::{ cursor, event, execute, event::{Event, KeyCode, KeyEventKind}, @@ -379,7 +442,7 @@ use std::time::Duration; /// TUIアプリケーションのメイン関数 pub fn run() -> Result<(), Box> { let font_data = include_bytes!("../fonts/NotoSerifJP-Regular.ttf"); - let font = FontRef::try_from_slice(font_data)?; + let font = FontRef::try_from_slice(font_data).map_err(|_| "Failed to load font from slice")?; let mut stdout = stdout(); terminal::enable_raw_mode()?; @@ -407,11 +470,14 @@ pub fn run() -> Result<(), Box> { Renderable::Text { text, anchor, - margin, + shift, + align, } => { - let pos = ui::calculate_position(anchor, margin, cols, rows); - let mut x = pos.0; - let y = pos.1; + // TUIでは複雑なアライメントは実装が難しいため、単純な位置計算に留める + let (text_width, text_height) = tui_renderer::measure_text(text); + let anchor_pos = ui::calculate_anchor_position(anchor, shift, cols, rows); + let (mut x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); + if y < 0 || y >= rows as i32 { continue; } @@ -473,32 +539,28 @@ fn handle_input(app: &mut App) -> std::io::Result<()> { extern crate alloc; use uefi::prelude::*; -use uefi::proto::console::gop::{BltOp, BltRegion, GraphicsOutput, Pixel}; -use uefi::proto::console::text::ScanCode; -use uefi::table::boot::{BootServices, EventType, TimerTrigger, Tpl}; -use uefi::table::Boot; +use uefi::proto::console::gop::{BltOp, BltPixel, BltRegion, GraphicsOutput}; +use uefi::proto::console::text::Key; +use uefi::boot::{EventType, TimerTrigger, Tpl}; use crate::app::App; -use crate::renderer::TEXT_COLOR; +use crate::renderer::{TEXT_COLOR, BG_COLOR}; use crate::ui::{self, Renderable}; use ab_glyph::{Font, FontRef, point, OutlinedGlyph, PxScale, ScaleFont}; use alloc::vec::Vec; -const BIG_FONT_SIZE: f32 = 48.0; const NORMAL_FONT_SIZE: f32 = 16.0; -const BG_COLOR: u32 = 0x00101010; - -#[no_mangle] -pub extern "efiapi" fn efi_main(image: Handle, st: SystemTable) -> Status { - let bt = st.boot_services(); +pub fn run() -> Status { + uefi::helpers::init().unwrap(); // Get Graphics Output Protocol - let gop_handle = bt.get_handle_for_protocol::().unwrap(); - let mut gop = bt.open_protocol_exclusive::(gop_handle).unwrap(); + let gop_handle = uefi::boot::get_handle_for_protocol::().unwrap(); + let mut gop = uefi::boot::open_protocol_exclusive::(gop_handle).unwrap(); // Get current mode info let mode_info = gop.current_mode_info(); let (width, height) = mode_info.resolution(); + let big_font_size = height as f32 * 0.5; // Load font let font_data: &[u8] = include_bytes!("../fonts/NotoSerifJP-Regular.ttf"); @@ -506,55 +568,66 @@ pub extern "efiapi" fn efi_main(image: Handle, st: SystemTable) -> Status let mut app = App::new(); - // Get input - let input = st.stdin(); - - // Create timer event - let timer_event = unsafe { bt.create_event(EventType::TIMER, Tpl::APPLICATION, None, None).unwrap() }; - bt.set_timer(&timer_event, TimerTrigger::Relative(100_000)).unwrap(); // 10ms + // Create timer event for the main loop tick + let timer_event = unsafe { uefi::boot::create_event(EventType::TIMER, Tpl::APPLICATION, None, None).unwrap() }; + uefi::boot::set_timer(&timer_event, TimerTrigger::Relative(100_000)).unwrap(); // 10ms tick - let mut events = [input.wait_for_key_event(), timer_event]; + let mut events = [timer_event]; while !app.should_quit { - // Wait for event - let index = bt.wait_for_event(&mut events).unwrap().unwrap(); - - if index == 0 { - // Key event - while let Ok(Some(key)) = input.read_key() { - if key.unicode_char != '\0' { - if key.unicode_char == '\x08' { + // Wait for the timer tick + uefi::boot::wait_for_event(&mut events).unwrap(); + + // Read all available keys by returning them from the closure + let keys: Vec = uefi::system::with_stdin(|stdin| { + let mut collected_keys = Vec::new(); + while let Ok(Some(key)) = stdin.read_key() { + collected_keys.push(key); + } + collected_keys + }); + + // Process the collected keys + for key in keys { + match key { + Key::Printable(c) => { + let ch: char = c.into(); + if ch == '\u{0008}' { // Backspace app.on_backspace(); } else { - app.on_key(key.unicode_char); - } - } else { - if key.scan_code == ScanCode::ESCAPE { - app.should_quit = true; + app.on_key(ch); } - } + }, + Key::Special(scan) if scan == uefi::proto::console::text::ScanCode::ESCAPE => { + app.should_quit = true; + }, + _ => {}, } } // Render - let mut pixel_buffer: Vec = alloc::vec![Pixel(((BG_COLOR >> 16) & 0xFF) as u8, ((BG_COLOR >> 8) & 0xFF) as u8, (BG_COLOR & 0xFF) as u8); width * height]; + let mut pixel_buffer: alloc::vec::Vec = alloc::vec![BltPixel::new(((BG_COLOR) & 0xFF) as u8, ((BG_COLOR >> 8) & 0xFF) as u8, ((BG_COLOR >> 16) & 0xFF) as u8); width * height]; let render_list = ui::build_ui(&app); for item in render_list { match item { - Renderable::BigText { text, anchor, margin } => { - let pos = ui::calculate_position(anchor, margin, width, height); + Renderable::BigText { text, anchor, shift, align } => { + let (text_width, text_height, _ascent) = measure_text(&font, text, big_font_size); + let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); + let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); draw_text( &mut pixel_buffer, width, &font, text, - (pos.0 as f32, pos.1 as f32), BIG_FONT_SIZE, + (x as f32, y as f32), big_font_size, ); } - Renderable::Text { text, anchor, margin } => { - let pos = ui::calculate_position(anchor, margin, width, height); + Renderable::Text { text, anchor, shift, align } => { + let (text_width, text_height, _ascent) = measure_text(&font, text, NORMAL_FONT_SIZE); + let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); + let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); draw_text( &mut pixel_buffer, width, &font, text, - (pos.0 as f32, pos.1 as f32), NORMAL_FONT_SIZE, + (x as f32, y as f32), NORMAL_FONT_SIZE, ); } } @@ -568,17 +641,15 @@ pub extern "efiapi" fn efi_main(image: Handle, st: SystemTable) -> Status dims: (width, height), }).unwrap(); - // Reset timer if it was the timer event - if index == 1 { - bt.set_timer(&timer_event, TimerTrigger::Relative(100_000)).unwrap(); - } + // Reset timer for the next tick + uefi::boot::set_timer(&events[0], TimerTrigger::Relative(100_000)).unwrap(); } Status::SUCCESS } fn draw_text( - buffer: &mut [Pixel], stride: usize, font: &FontRef, text: &str, + buffer: &mut [BltPixel], stride: usize, font: &FontRef, text: &str, pos: (f32, f32), font_size: f32, ) { let scale = PxScale::from(font_size); @@ -587,17 +658,22 @@ fn draw_text( let mut pen_x = pos.0; let pen_y = pos.1 + ascent; + let mut last_glyph = None; for character in text.chars() { let glyph_id = font.glyph_id(character); + if let Some(last) = last_glyph { + pen_x += scaled_font.kern(last, glyph_id); + } let glyph = glyph_id.with_scale_and_position(scale, point(pen_x, pen_y)); if let Some(outlined) = font.outline_glyph(glyph) { draw_glyph_to_pixel_buffer(buffer, stride, &outlined); } pen_x += scaled_font.h_advance(glyph_id); + last_glyph = Some(glyph_id); } } -fn draw_glyph_to_pixel_buffer(buffer: &mut [Pixel], stride: usize, outlined: &OutlinedGlyph) { +fn draw_glyph_to_pixel_buffer(buffer: &mut [BltPixel], stride: usize, outlined: &OutlinedGlyph) { let bounds = outlined.px_bounds(); outlined.draw(|x, y, c| { let buffer_x = bounds.min.x as i32 + x as i32; @@ -605,19 +681,42 @@ fn draw_glyph_to_pixel_buffer(buffer: &mut [Pixel], stride: usize, outlined: &Ou let height = buffer.len() / stride; if buffer_x >= 0 && buffer_x < stride as i32 && buffer_y >= 0 && buffer_y < height as i32 { let index = (buffer_y as usize) * stride + (buffer_x as usize); - let text_r = ((TEXT_COLOR >> 16) & 0xFF) as f32; - let text_g = ((TEXT_COLOR >> 8) & 0xFF) as f32; let text_b = (TEXT_COLOR & 0xFF) as f32; - let bg_r = buffer[index].0 as f32; - let bg_g = buffer[index].1 as f32; - let bg_b = buffer[index].2 as f32; - let r = (text_r * c + bg_r * (1.0 - c)) as u8; - let g = (text_g * c + bg_g * (1.0 - c)) as u8; + let text_g = ((TEXT_COLOR >> 8) & 0xFF) as f32; + let text_r = ((TEXT_COLOR >> 16) & 0xFF) as f32; + let bg_b = buffer[index].blue as f32; + let bg_g = buffer[index].green as f32; + let bg_r = buffer[index].red as f32; let b = (text_b * c + bg_b * (1.0 - c)) as u8; - buffer[index] = Pixel(r, g, b); + let g = (text_g * c + bg_g * (1.0 - c)) as u8; + let r = (text_r * c + bg_r * (1.0 - c)) as u8; + buffer[index] = BltPixel::new(b, g, r); } }); } + +/// テキストの描画サイズを計算する +fn measure_text(font: &FontRef, text: &str, size: f32) -> (u32, u32, f32) { + let scale = PxScale::from(size); + let scaled_font = font.as_scaled(scale); + let mut total_width = 0.0; + + let mut last_glyph_id = None; + for c in text.chars() { + if c == '\n' { + continue; + } + let glyph = font.glyph_id(c); + if let Some(last_id) = last_glyph_id { + total_width += scaled_font.kern(last_id, glyph); + } + total_width += scaled_font.h_advance(glyph); + last_glyph_id = Some(glyph); + } + let height = scaled_font.ascent() - scaled_font.descent(); + (total_width as u32, height as u32, scaled_font.ascent()) +} + --- ./src\ui.rs @@ -649,11 +748,34 @@ pub enum Anchor { BottomRight, } -/// Anchorからのオフセット(余白)を定義する構造体 +/// Anchorからのオフセット(移動量)を定義する構造体 #[derive(Clone, Copy)] -pub struct Margin { - pub x: i32, - pub y: i32, +pub struct Shift { + pub x: f32, + pub y: f32, +} + +/// 水平方向の揃え +#[derive(Clone, Copy)] +pub enum HorizontalAlign { + Left, + Center, + Right, +} + +/// 垂直方向の揃え +#[derive(Clone, Copy)] +pub enum VerticalAlign { + Top, + Center, + Bottom, +} + +/// テキストの揃え方を定義する構造体 +#[derive(Clone, Copy)] +pub struct Align { + pub horizontal: HorizontalAlign, + pub vertical: VerticalAlign, } /// 画面に描画すべき要素の種類とレイアウト情報を定義するenum @@ -662,13 +784,15 @@ pub enum Renderable<'a> { Text { text: &'a str, anchor: Anchor, - margin: Margin, + shift: Shift, + align: Align, }, /// 大きなフォントサイズで描画されるテキスト BigText { text: &'a str, anchor: Anchor, - margin: Margin, + shift: Shift, + align: Align, }, } @@ -679,19 +803,27 @@ pub fn build_ui<'a>(app: &'a App) -> Vec> { Renderable::BigText { text: &app.input_text, anchor: Anchor::CenterLeft, - margin: Margin { x: 0, y: 0 }, + shift: Shift { x: 0.02, y: 0.0 }, // 画面幅の2%右にずらす + align: Align { + horizontal: HorizontalAlign::Left, + vertical: VerticalAlign::Center, + }, }, // 画面左下に表示するステータステキスト Renderable::Text { text: &app.status_text, anchor: Anchor::BottomLeft, - margin: Margin { x: 5, y: -5 }, + shift: Shift { x: 0.01, y: -0.02 }, // 画面幅の1%右、画面高さの2%上にずらす + align: Align { + horizontal: HorizontalAlign::Left, + vertical: VerticalAlign::Bottom, + }, }, ] } -/// AnchorとMarginから、具体的な描画開始座標(x, y)を計算する -pub fn calculate_position(anchor: Anchor, margin: Margin, width: usize, height: usize) -> (i32, i32) { +/// AnchorとShiftから、基準となる座標(x, y)を計算する +pub fn calculate_anchor_position(anchor: Anchor, shift: Shift, width: usize, height: usize) -> (i32, i32) { let (w, h) = (width as i32, height as i32); let base_pos = match anchor { Anchor::TopLeft => (0, 0), @@ -704,7 +836,34 @@ pub fn calculate_position(anchor: Anchor, margin: Margin, width: usize, height: Anchor::BottomCenter => (w / 2, h), Anchor::BottomRight => (w, h), }; - (base_pos.0 + margin.x, base_pos.1 + margin.y) + let shift_x = (width as f32 * shift.x) as i32; + let shift_y = (height as f32 * shift.y) as i32; + (base_pos.0 + shift_x, base_pos.1 + shift_y) +} + +/// 基準点、テキストの寸法、揃え方から、最終的な描画開始座標(左上)を計算する +pub fn calculate_aligned_position( + anchor_pos: (i32, i32), + text_width: u32, + text_height: u32, + align: Align, +) -> (i32, i32) { + let (tw, th) = (text_width as i32, text_height as i32); + let (ax, ay) = anchor_pos; + + let x = match align.horizontal { + HorizontalAlign::Left => ax, + HorizontalAlign::Center => ax - tw / 2, + HorizontalAlign::Right => ax - tw, + }; + + let y = match align.vertical { + VerticalAlign::Top => ay, + VerticalAlign::Center => ay - th / 2, + VerticalAlign::Bottom => ay - th, + }; + + (x, y) } --- @@ -719,9 +878,6 @@ use wasm_bindgen::prelude::*; use wasm_bindgen::Clamped; use web_sys::{CanvasRenderingContext2d, ImageData, KeyboardEvent}; -const WIDTH: usize = 800; -const HEIGHT: usize = 100; -const BIG_FONT_SIZE: f32 = 48.0; const NORMAL_FONT_SIZE: f32 = 16.0; /// WASMモジュールのエントリーポイント @@ -732,17 +888,45 @@ pub fn start() -> Result<(), JsValue> { let document = window.document().unwrap(); let body = document.body().unwrap(); - let canvas = document.create_element("canvas")?.dyn_into::()?; - canvas.set_width(WIDTH as u32); - canvas.set_height(HEIGHT as u32); + let canvas = document + .create_element("canvas")? + .dyn_into::()?; body.append_child(&canvas)?; - let context = canvas.get_context("2d")?.unwrap().dyn_into::()?; + let context = + canvas.get_context("2d")?.unwrap().dyn_into::()?; let font = FontRef::try_from_slice(include_bytes!("../fonts/NotoSerifJP-Regular.ttf")) .map_err(|e| JsValue::from_str(&e.to_string()))?; let app = Rc::new(RefCell::new(App::new())); + let size = Rc::new(RefCell::new((0, 0))); + + // 初期サイズ設定とリサイズハンドラ + { + let window_clone = window.clone(); + let canvas_clone = canvas.clone(); + let size_clone = size.clone(); + let resize_handler = Closure::::new(move || { + let width = window_clone.inner_width().unwrap().as_f64().unwrap() as u32; + let height = window_clone.inner_height().unwrap().as_f64().unwrap() as u32; + canvas_clone.set_width(width); + canvas_clone.set_height(height); + *size_clone.borrow_mut() = (width as usize, height as usize); + }); + window.add_event_listener_with_callback("resize", resize_handler.as_ref().unchecked_ref())?; + resize_handler.forget(); + // 初期サイズを設定するために一度呼び出す + let window_clone = window.clone(); + let canvas_clone = canvas.clone(); + let size_clone = size.clone(); + let width = window_clone.inner_width().unwrap().as_f64().unwrap() as u32; + let height = window_clone.inner_height().unwrap().as_f64().unwrap() as u32; + canvas_clone.set_width(width); + canvas_clone.set_height(height); + *size_clone.borrow_mut() = (width as usize, height as usize); + } + // キーボードイベントのリスナーを設定 { let app_clone = app.clone(); @@ -763,10 +947,12 @@ pub fn start() -> Result<(), JsValue> { let f = Rc::new(RefCell::new(None)); let g = f.clone(); *g.borrow_mut() = Some(Closure::::new(move || { + let (width, height) = *size.borrow(); + let big_font_size = height as f32 * 0.5; let app = app.borrow(); // 描画中は不変借用 // 1. 背景色でピクセルバッファをクリア - let mut pixel_buffer = vec![BG_COLOR; WIDTH * HEIGHT]; + let mut pixel_buffer = vec![BG_COLOR; width * height]; // 2. UI定義から描画リストを取得 let render_list = ui::build_ui(&app); @@ -774,29 +960,51 @@ pub fn start() -> Result<(), JsValue> { // 3. 描画リストを解釈して描画 for item in render_list { match item { - Renderable::BigText { text, anchor, margin } => { - let pos = ui::calculate_position(anchor, margin, WIDTH, HEIGHT); + Renderable::BigText { text, anchor, shift, align } => { + let (text_width, text_height) = gui_renderer::measure_text(&font, text, big_font_size); + let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); + let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( - &mut pixel_buffer, WIDTH, &font, text, - (pos.0 as f32, pos.1 as f32), BIG_FONT_SIZE, + &mut pixel_buffer, + width, + &font, + text, + (x as f32, y as f32), + big_font_size, ); } - Renderable::Text { text, anchor, margin } => { - let pos = ui::calculate_position(anchor, margin, WIDTH, HEIGHT); + Renderable::Text { text, anchor, shift, align } => { + let (text_width, text_height) = gui_renderer::measure_text(&font, text, NORMAL_FONT_SIZE); + let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); + let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( - &mut pixel_buffer, WIDTH, &font, text, - (pos.0 as f32, pos.1 as f32), NORMAL_FONT_SIZE, + &mut pixel_buffer, + width, + &font, + text, + (x as f32, y as f32), + NORMAL_FONT_SIZE, ); } } } - + // 4. 完成したバッファをCanvasに転送 - let mut u8_buffer = Vec::with_capacity(WIDTH * HEIGHT * 4); + let mut u8_buffer = Vec::with_capacity(width * height * 4); for pixel in pixel_buffer.iter() { - u8_buffer.extend_from_slice(&[((*pixel >> 16) & 0xFF) as u8, ((*pixel >> 8) & 0xFF) as u8, (*pixel & 0xFF) as u8, 255]); + u8_buffer.extend_from_slice(&[ + ((*pixel >> 16) & 0xFF) as u8, + ((*pixel >> 8) & 0xFF) as u8, + (*pixel & 0xFF) as u8, + 255, + ]); } - let image_data = ImageData::new_with_u8_clamped_array_and_sh(Clamped(&u8_buffer), WIDTH as u32, HEIGHT as u32).unwrap(); + let image_data = ImageData::new_with_u8_clamped_array_and_sh( + Clamped(&u8_buffer), + width as u32, + height as u32, + ) + .unwrap(); context.put_image_data(&image_data, 0.0, 0.0).unwrap(); // 次のフレームを要求 @@ -809,7 +1017,11 @@ pub fn start() -> Result<(), JsValue> { /// requestAnimationFrameを呼び出すヘルパー関数 fn request_animation_frame(f: &Closure) { - web_sys::window().unwrap().request_animation_frame(f.as_ref().unchecked_ref()).unwrap(); + web_sys::window() + .unwrap() + .request_animation_frame(f.as_ref().unchecked_ref()) + .unwrap(); } + --- diff --git a/src/gui.rs b/src/gui.rs index 3e38867..ef65569 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -50,7 +50,7 @@ pub fn run() -> Result<(), Box> { for item in render_list { match item { Renderable::BigText { text, anchor, shift, align } => { - let (text_width, text_height) = gui_renderer::measure_text(&font, text, big_font_size); + let (text_width, text_height, _ascent) = gui_renderer::measure_text(&font, text, big_font_size); let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( @@ -59,7 +59,7 @@ pub fn run() -> Result<(), Box> { ); } Renderable::Text { text, anchor, shift, align } => { - let (text_width, text_height) = gui_renderer::measure_text(&font, text, NORMAL_FONT_SIZE); + let (text_width, text_height, _ascent) = gui_renderer::measure_text(&font, text, NORMAL_FONT_SIZE); let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( @@ -143,4 +143,4 @@ fn key_to_char(key: Key, is_shift: bool) -> Option { (Key::Minus, false) => Some('-'), (Key::Minus, true) => Some('_'), _ => None, } -} \ No newline at end of file +} diff --git a/src/renderer.rs b/src/renderer.rs index f75bbbb..8b683a5 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -29,21 +29,29 @@ pub mod gui_renderer { buffer: &mut [u32], stride: usize, font: &FontRef, text: &str, pos: (f32, f32), font_size: f32, ) { - let scale = font_size / (font.ascent_unscaled() - font.descent_unscaled()); + let scale = PxScale::from(font_size); + let scaled_font = font.as_scaled(scale); + let ascent = scaled_font.ascent(); let mut pen_x = pos.0; - let pen_y = pos.1; + let pen_y = pos.1 + ascent; + let mut last_glyph = None; for character in text.chars() { - let glyph = font.glyph_id(character).with_scale_and_position(font_size, point(pen_x, pen_y)); + let glyph_id = font.glyph_id(character); + if let Some(last) = last_glyph { + pen_x += scaled_font.kern(last, glyph_id); + } + let glyph = glyph_id.with_scale_and_position(scale, point(pen_x, pen_y)); if let Some(outlined) = font.outline_glyph(glyph) { draw_glyph_to_pixel_buffer(buffer, stride, &outlined); } - pen_x += font.h_advance_unscaled(font.glyph_id(character)) * scale; + pen_x += scaled_font.h_advance(glyph_id); + last_glyph = Some(glyph_id); } } /// アウトライン化されたグリフをピクセルバッファに描画する(内部関数) - fn draw_glyph_to_pixel_buffer(buffer: &mut [u32], stride: usize, outlined: &OutlinedGlyph) { + fn draw_glyph_to_pixel_buffer(buffer: &mut [u32], stride: usize, outlined: &OutlinedGlyph) { let bounds = outlined.px_bounds(); outlined.draw(|x, y, c| { let buffer_x = bounds.min.x as i32 + x as i32; @@ -54,9 +62,9 @@ pub mod gui_renderer { let text_r = ((TEXT_COLOR >> 16) & 0xFF) as f32; let text_g = ((TEXT_COLOR >> 8) & 0xFF) as f32; let text_b = (TEXT_COLOR & 0xFF) as f32; - let bg_r = ((BG_COLOR >> 16) & 0xFF) as f32; - let bg_g = ((BG_COLOR >> 8) & 0xFF) as f32; - let bg_b = (BG_COLOR & 0xFF) as f32; + let bg_r = ((buffer[index] >> 16) & 0xFF) as f32; + let bg_g = ((buffer[index] >> 8) & 0xFF) as f32; + let bg_b = (buffer[index] & 0xFF) as f32; let r = (text_r * c + bg_r * (1.0 - c)) as u32; let g = (text_g * c + bg_g * (1.0 - c)) as u32; let b = (text_b * c + bg_b * (1.0 - c)) as u32; @@ -66,11 +74,10 @@ pub mod gui_renderer { } /// テキストの描画サイズ(幅と高さ)を計算する - pub fn measure_text(font: &FontRef, text: &str, size: f32) -> (u32, u32) { + pub fn measure_text(font: &FontRef, text: &str, size: f32) -> (u32, u32, f32) { let scale = PxScale::from(size); let scaled_font = font.as_scaled(scale); let mut total_width = 0.0; - let mut max_height = 0.0; let mut last_glyph_id = None; for c in text.chars() { @@ -81,16 +88,11 @@ pub mod gui_renderer { if let Some(last_id) = last_glyph_id { total_width += scaled_font.kern(last_id, glyph); } - if let Some(outlined_glyph) = font.outline_glyph(glyph.with_scale(scale)) { - let bounds = outlined_glyph.px_bounds(); - total_width += bounds.width(); - if bounds.height() > max_height { - max_height = bounds.height(); - } - } + total_width += scaled_font.h_advance(glyph); last_glyph_id = Some(glyph); } - (total_width as u32, max_height as u32) + let height = scaled_font.ascent() - scaled_font.descent(); + (total_width as u32, height as u32, scaled_font.ascent()) } } @@ -104,7 +106,7 @@ pub mod tui_renderer { let font_size = height as f32 * 0.8; let scale = font_size / (font.ascent_unscaled() - font.descent_unscaled()); let mut pen_x = 2.0; - let mut pen_y = height as f32 * 0.7; + let pen_y = height as f32 * 0.7; for character in text.chars() { let glyph = font.glyph_id(character).with_scale_and_position(font_size, point(pen_x, pen_y)); @@ -126,7 +128,11 @@ pub mod tui_renderer { if buffer_x < width && buffer_y < height { let index = buffer_y * width + buffer_x; let coverage_char = match (c * 4.0).round() as u8 { - 0 => ' ', 1 => '.', 2 => '*', 3 => '#', _ => '@', + 0 => ' ', + 1 => '.', + 2 => '*', + 3 => '#', + _ => '@', }; if buffer[index] == ' ' { buffer[index] = coverage_char; } } diff --git a/src/uefi.rs b/src/uefi.rs index 16bfaa5..7e4f5b8 100644 --- a/src/uefi.rs +++ b/src/uefi.rs @@ -77,7 +77,7 @@ pub fn run() -> Status { for item in render_list { match item { Renderable::BigText { text, anchor, shift, align } => { - let (text_width, text_height) = measure_text(&font, text, big_font_size); + let (text_width, text_height, _ascent) = measure_text(&font, text, big_font_size); let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); draw_text( @@ -86,7 +86,7 @@ pub fn run() -> Status { ); } Renderable::Text { text, anchor, shift, align } => { - let (text_width, text_height) = measure_text(&font, text, NORMAL_FONT_SIZE); + let (text_width, text_height, _ascent) = measure_text(&font, text, NORMAL_FONT_SIZE); let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); draw_text( @@ -122,13 +122,18 @@ fn draw_text( let mut pen_x = pos.0; let pen_y = pos.1 + ascent; + let mut last_glyph = None; for character in text.chars() { let glyph_id = font.glyph_id(character); + if let Some(last) = last_glyph { + pen_x += scaled_font.kern(last, glyph_id); + } let glyph = glyph_id.with_scale_and_position(scale, point(pen_x, pen_y)); if let Some(outlined) = font.outline_glyph(glyph) { draw_glyph_to_pixel_buffer(buffer, stride, &outlined); } pen_x += scaled_font.h_advance(glyph_id); + last_glyph = Some(glyph_id); } } @@ -155,11 +160,10 @@ fn draw_glyph_to_pixel_buffer(buffer: &mut [BltPixel], stride: usize, outlined: } /// テキストの描画サイズを計算する -fn measure_text(font: &FontRef, text: &str, size: f32) -> (u32, u32) { +fn measure_text(font: &FontRef, text: &str, size: f32) -> (u32, u32, f32) { let scale = PxScale::from(size); let scaled_font = font.as_scaled(scale); let mut total_width = 0.0; - let mut max_height = 0.0; let mut last_glyph_id = None; for c in text.chars() { @@ -170,14 +174,9 @@ fn measure_text(font: &FontRef, text: &str, size: f32) -> (u32, u32) { if let Some(last_id) = last_glyph_id { total_width += scaled_font.kern(last_id, glyph); } - if let Some(outlined_glyph) = font.outline_glyph(glyph.with_scale(scale)) { - let bounds = outlined_glyph.px_bounds(); - total_width += bounds.width(); - if bounds.height() > max_height { - max_height = bounds.height(); - } - } + total_width += scaled_font.h_advance(glyph); last_glyph_id = Some(glyph); } - (total_width as u32, max_height as u32) + let height = scaled_font.ascent() - scaled_font.descent(); + (total_width as u32, height as u32, scaled_font.ascent()) } diff --git a/src/wasm.rs b/src/wasm.rs index 0733878..c121425 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -1,7 +1,7 @@ use crate::app::App; use crate::renderer::{gui_renderer, BG_COLOR}; use crate::ui::{self, Renderable}; -use ab_glyph::{Font, FontRef}; +use ab_glyph::{FontRef}; use std::cell::RefCell; use std::rc::Rc; use wasm_bindgen::prelude::*; @@ -91,7 +91,7 @@ pub fn start() -> Result<(), JsValue> { for item in render_list { match item { Renderable::BigText { text, anchor, shift, align } => { - let (text_width, text_height) = gui_renderer::measure_text(&font, text, big_font_size); + let (text_width, text_height, _) = gui_renderer::measure_text(&font, text, big_font_size); let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( @@ -104,7 +104,7 @@ pub fn start() -> Result<(), JsValue> { ); } Renderable::Text { text, anchor, shift, align } => { - let (text_width, text_height) = gui_renderer::measure_text(&font, text, NORMAL_FONT_SIZE); + let (text_width, text_height, _) = gui_renderer::measure_text(&font, text, NORMAL_FONT_SIZE); let anchor_pos = ui::calculate_anchor_position(anchor, shift, width, height); let (x, y) = ui::calculate_aligned_position(anchor_pos, text_width, text_height, align); gui_renderer::draw_text( diff --git a/uefi_image/EFI/BOOT/BOOTX64.EFI b/uefi_image/EFI/BOOT/BOOTX64.EFI index b517c17f2346901f69d4a6e16499864777cb303b..867857d46999b01adf0ef8a3eb246f9211a52e12 100644 GIT binary patch delta 43369 zcmag{2Uu0d^FNNWd*E_uf(4WgdMP#pMMXsgMZG90c5H}UV{eHi2zC d+#`8e2>( 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 F{s)*V){p=I