Implemented font outline settings dialog. - icy_draw - icy_draw is the successor to mystic draw. fork / mirror
 (HTM) git clone https://git.drkhsh.at/icy_draw.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit f74759aab4f5af9eaf482a8ef6e90f69da423e9c
 (DIR) parent ca6ccc903054e0e01401993f7460cea033c4a5a0
 (HTM) Author: Mike Krüger <mkrueger@posteo.de>
       Date:   Thu, 27 Jul 2023 18:40:51 +0200
       
       Implemented font outline settings dialog.
       
       Diffstat:
         M i18n/en/icy_draw.ftl                |       7 +++++--
         M src/model/tool/brush_imp.rs         |       2 +-
         M src/model/tool/font_imp.rs          |       4 ++--
         M src/ui/main_window.rs               |      59 ++++++++++++++++++-------------
         M src/ui/mod.rs                       |       6 ++++++
         A src/ui/select_outline_dialog.rs     |     148 +++++++++++++++++++++++++++++++
         A src/ui/settings.rs                  |       8 ++++++++
       
       7 files changed, 205 insertions(+), 29 deletions(-)
       ---
 (DIR) diff --git a/i18n/en/icy_draw.ftl b/i18n/en/icy_draw.ftl
       @@ -9,6 +9,7 @@ menu-set-canvas-size=Set Canvas Size…
        menu-close=Close
        menu-save-as=Save As…
        menu-export=Export…
       +menu-edit-font-outline=Font Outline…
        
        menu-edit=Edit
        menu-undo=Undo
       @@ -85,4 +86,6 @@ export-compression-level-off=Off
        export-compression-level-medium=Medium
        export-compression-level-high=High
        
       -select-character-title=Select Character
       -\ No newline at end of file
       +select-character-title=Select Character
       +
       +select-outline-style-title=Outline Font Style Type
       +\ No newline at end of file
 (DIR) diff --git a/src/model/tool/brush_imp.rs b/src/model/tool/brush_imp.rs
       @@ -188,7 +188,7 @@ pub fn draw_glyph(ui: &mut egui::Ui, buf: Arc<Mutex<BufferView>>, ui_result: &mu
                scale * font.size.width as f32,
                scale * font.size.height as f32,
            ));
       -    let mut response = ui.interact(stroke_rect, id, Sense::click());
       +    let response = ui.interact(stroke_rect, id, Sense::click());
        
            let col = if response.hovered() {
                Color32::WHITE
 (DIR) diff --git a/src/model/tool/font_imp.rs b/src/model/tool/font_imp.rs
       @@ -3,7 +3,7 @@ use std::{
            sync::{Arc, Mutex},
        };
        
       -use crate::ansi_editor::BufferView;
       +use crate::{ansi_editor::BufferView, SETTINGS};
        
        use super::{Event, MKey,  MModifiers, Position, Tool, ToolUiResult};
        use directories::ProjectDirs;
       @@ -245,7 +245,7 @@ impl Tool for FontTool {
                        let c_pos = editor.get_caret_position();
                        editor.begin_atomic_undo();
                        let attr = editor.caret.get_attribute();
       -                let opt_size = font.render(&mut editor.buf, 0, c_pos, attr, 0, ch as u8);
       +                let opt_size = font.render(&mut editor.buf, 0, c_pos, attr, unsafe { SETTINGS.font_outline_style }, ch as u8);
                        if let Some(size) = opt_size {
                            editor.set_caret(c_pos.x + size.width as i32 + font.spaces, c_pos.y);
                            let new_pos = editor.get_caret_position();
 (DIR) diff --git a/src/ui/main_window.rs b/src/ui/main_window.rs
       @@ -5,7 +5,7 @@ use std::{
            time::Duration, cell::RefCell, rc::Rc,
        };
        
       -use crate::{model::Tool, Document, EditSauceDialog, FontEditor, NewFileDialog, ModalDialog};
       +use crate::{model::Tool, Document, EditSauceDialog, FontEditor, NewFileDialog, ModalDialog, SelectOutlineDialog};
        use eframe::{
            egui::{self, menu, Response, SidePanel, TextStyle, TopBottomPanel, Ui, Modifiers},
            epaint::pos2,
       @@ -253,9 +253,43 @@ impl MainWindow {
                            )));
                            ui.close_menu();
                        }
       +                ui.separator();
       +                if ui
       +                    .add(
       +                        egui::Button::new(fl!(crate::LANGUAGE_LOADER, "menu-edit-font-outline"))
       +                            .wrap(false),
       +                    )
       +                    .clicked()
       +                {
       +                    self.modal_dialog = Some(Box::new(SelectOutlineDialog::new()));
       +                    ui.close_menu();
       +                }
        
        
                        ui.separator();
       +                let button: Response =
       +                    button_with_shortcut(ui, true, fl!(crate::LANGUAGE_LOADER, "menu-close"), "Ctrl+Q");
       +                if button.clicked() {
       +                    _frame.close();
       +                    ui.close_menu();
       +                }
       +            });
       +
       +            ui.menu_button(fl!(crate::LANGUAGE_LOADER, "menu-edit"), |ui| {
       +                let button: Response =
       +                    button_with_shortcut(ui, has_buffer, fl!(crate::LANGUAGE_LOADER, "menu-undo"), "Ctrl+Z");
       +                if button.clicked() {
       +                    self.undo_command();
       +                    ui.close_menu();
       +                }
       +    
       +                let button: Response =
       +                    button_with_shortcut(ui, has_buffer, fl!(crate::LANGUAGE_LOADER, "menu-redo"), "Ctrl+Shift+Z");
       +                if button.clicked() {
       +                    self.redo_command();
       +                    ui.close_menu();
       +                }
       +                ui.separator();
                        if ui
                            .add_enabled(
                                has_buffer,
       @@ -292,29 +326,6 @@ impl MainWindow {
                            )));
                            ui.close_menu();
                        }
       -                ui.separator();
       -                let button: Response =
       -                    button_with_shortcut(ui, true, fl!(crate::LANGUAGE_LOADER, "menu-close"), "Ctrl+Q");
       -                if button.clicked() {
       -                    _frame.close();
       -                    ui.close_menu();
       -                }
       -            });
       -
       -            ui.menu_button(fl!(crate::LANGUAGE_LOADER, "menu-edit"), |ui| {
       -                let button: Response =
       -                    button_with_shortcut(ui, has_buffer, fl!(crate::LANGUAGE_LOADER, "menu-undo"), "Ctrl+Z");
       -                if button.clicked() {
       -                    self.undo_command();
       -                    ui.close_menu();
       -                }
       -    
       -                let button: Response =
       -                    button_with_shortcut(ui, has_buffer, fl!(crate::LANGUAGE_LOADER, "menu-redo"), "Ctrl+Shift+Z");
       -                if button.clicked() {
       -                    self.redo_command();
       -                    ui.close_menu();
       -                }
                    });
        
                    ui.menu_button(fl!(crate::LANGUAGE_LOADER, "menu-selection"), |ui| {
 (DIR) diff --git a/src/ui/mod.rs b/src/ui/mod.rs
       @@ -39,6 +39,12 @@ pub use layer_view::*;
        mod select_character_dialog;
        pub use select_character_dialog::*;
        
       +mod select_outline_dialog;
       +pub use select_outline_dialog::*;
       +
       +mod settings;
       +pub use settings::*;
       +
        pub type TerminalResult<T> = Result<T, Box<dyn Error>>;
        
        pub trait ModalDialog {
 (DIR) diff --git a/src/ui/select_outline_dialog.rs b/src/ui/select_outline_dialog.rs
       @@ -0,0 +1,147 @@
       +use eframe::{egui::{self}, epaint::{Vec2, Rect, Color32, Rounding}};
       +use egui_modal::Modal;
       +use i18n_embed_fl::fl;
       +use icy_engine::{BitFont, TheDrawFont};
       +
       +use crate::{TerminalResult, ModalDialog};
       +
       +pub struct SelectOutlineDialog {
       +    should_commit: bool,
       +    selected_outline: usize,
       +    font: BitFont
       +}
       +
       +impl SelectOutlineDialog {
       +    pub fn new() -> Self {
       +        SelectOutlineDialog {
       +            should_commit: false,
       +            selected_outline: unsafe { super::SETTINGS.font_outline_style },
       +            font: BitFont::default()
       +        }
       +    }
       +
       +    fn draw_outline_glyph(&mut self, ui: &mut egui::Ui, outline_style: usize)
       +    {
       +        let scale = 1.;
       +        let border = 4.0;
       +
       +        let (_id, stroke_rect) = ui.allocate_space(Vec2::new(
       +            2. * border + scale * self.font.size.width as f32 * OUTLINE_WIDTH as f32,
       +            2. * border + scale * self.font.size.height as f32 * OUTLINE_HEIGHT as f32,
       +        ));
       +
       +        let painter = ui.painter_at(stroke_rect);
       +        let s = self.font.size;
       +        let mut col = if self.selected_outline == outline_style { Color32::GRAY } else { Color32::DARK_GRAY };
       +        let bg_color =  if self.selected_outline == outline_style { Color32::DARK_BLUE } else { Color32::BLACK };
       +
       +        if let Some(pos) = ui.input(|i| i.pointer.hover_pos()) {
       +            if stroke_rect.contains(pos) {
       +
       +                if ui.input(|i| i.pointer.primary_clicked()) {
       +                    self.selected_outline = outline_style;
       +                }
       +                col = Color32::WHITE;
       +            }
       +        }
       +        painter.rect_filled(stroke_rect, Rounding::none(), bg_color);
       +
       +
       +        for h in 0..OUTLINE_HEIGHT {
       +            for w in 0..OUTLINE_WIDTH {
       +                let ch = TheDrawFont::transform_outline(outline_style, OUTLINE_FONT_CHAR[w + h * OUTLINE_WIDTH]);
       +                let ch = unsafe { char::from_u32_unchecked(ch as u32) };
       +
       +                let xs = w as f32 * scale * self.font.size.width as f32;
       +                let ys = h as f32 * scale * self.font.size.height as f32;
       +                if let Some(glyph) = self.font.get_glyph(ch) {
       +                    for y in 0..s.height {
       +                        for x in 0..s.width {
       +                            if glyph.data[y as usize] & (128 >> x) != 0 {
       +                                painter.rect_filled(
       +                                    Rect::from_min_size(
       +                                        egui::Pos2::new(
       +                                            border + xs + stroke_rect.left() + x as f32 * scale,
       +                                            border + ys + stroke_rect.top() + y as f32 * scale,
       +                                        ),
       +                                        Vec2::new(scale, scale),
       +                                    ),
       +                                    Rounding::none(),
       +                                    col,
       +                                );
       +                            }
       +                        }
       +                    }
       +                }
       +            }
       +        }
       +    }
       +}
       +
       +const OUTLINE_WIDTH: usize = 8;
       +const OUTLINE_HEIGHT: usize = 6;
       +const OUTLINE_FONT_CHAR: [u8; 48]= [
       +    69,65,65,65,65,65,65,70,
       +    67,79,71,66,66,72,79,68,
       +    67,79,73,65,65,74,79,68,
       +    67,79,71,66,66,72,79,68,
       +    67,79,68,64,64,67,79,68,
       +    75,66,76,64,64,75,66,76
       +];
       +
       +
       +impl ModalDialog for SelectOutlineDialog {
       +    fn show(&mut self, ctx: &egui::Context) -> bool {
       +
       +        let mut result = false;
       +        let modal = Modal::new(ctx, "my_modal");
       +
       +        modal.show(|ui| {
       +            modal.title(ui, fl!(crate::LANGUAGE_LOADER, "select-outline-style-title"));
       +
       +            modal.frame(ui, |ui| {
       +                ui.add_space(8.0);
       +                for style in 0..TheDrawFont::OUTLINE_STYLES / 4 {
       +                    ui.horizontal(|ui| {
       +                        ui.add_space(4.0);
       +                        for i in 0..4 {
       +                            self.draw_outline_glyph(ui, style * 4 + i);
       +                            if i < 3  {
       +                                ui.add_space(8.0);
       +                            }
       +                        }
       +                    });
       +                    ui.end_row();
       +                    ui.add_space(8.0);
       +                };
       +            });
       +
       +            modal.buttons(ui, |ui| {
       +                if ui
       +                    .button(fl!(crate::LANGUAGE_LOADER, "new-file-ok"))
       +                    .clicked()
       +                {
       +                    self.should_commit = true;
       +                    result = true;
       +                }
       +                if ui
       +                    .button(fl!(crate::LANGUAGE_LOADER, "new-file-cancel"))
       +                    .clicked()
       +                {
       +                    result = true;
       +                }
       +            });
       +        });
       +        modal.open();
       +        result
       +    }
       +
       +    fn should_commit(&self) -> bool { self.should_commit }
       +
       +    fn commit(&self, _editor: &mut crate::model::Editor) -> TerminalResult<bool>  {
       +        unsafe {
       +            super::SETTINGS.font_outline_style = self.selected_outline;
       +        }
       +        Ok(true)
       +    }
       +}
       +\ No newline at end of file
 (DIR) diff --git a/src/ui/settings.rs b/src/ui/settings.rs
       @@ -0,0 +1,7 @@
       +pub struct Settings {
       +    pub font_outline_style: usize
       +}
       +
       +pub static mut SETTINGS: Settings = Settings {
       +    font_outline_style: 0
       +};
       +\ No newline at end of file