mod.rs - 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
       ---
       mod.rs (25877B)
       ---
            1 use std::{path::Path, sync::Arc};
            2 
            3 use eframe::{
            4     egui::{self, Button, ScrollArea, SidePanel, TextEdit, TopBottomPanel},
            5     epaint::{mutex::Mutex, Vec2},
            6 };
            7 use egui::{load::SizedTexture, Image, Rect, TextureHandle};
            8 use i18n_embed_fl::fl;
            9 use icy_engine::{AttributedChar, BitFont, Buffer, EngineResult, FontGlyph, Layer, Size, TextAttribute, TextPane, TheDrawFont};
           10 use icy_engine_egui::{show_terminal_area, BufferView};
           11 
           12 use crate::{
           13     model::{click_imp::VALID_OUTLINE_CHARS, Tool},
           14     AnsiEditor, BitFontEditor, ClipboardHandler, Document, DocumentOptions, DrawGlyphStyle, Message, SelectOutlineDialog, TerminalResult, UndoHandler,
           15     SETTINGS,
           16 };
           17 
           18 pub struct CharFontEditor {
           19     id: usize,
           20     font: BitFont,
           21     selected_char_opt: Option<char>,
           22     old_selected_char_opt: Option<char>,
           23 
           24     outline_previewbuffer_view: Arc<Mutex<BufferView>>,
           25 
           26     ansi_editor: AnsiEditor,
           27     selected_font: usize,
           28     fonts: Vec<TheDrawFont>,
           29     undostack_len: usize,
           30     last_update_preview: usize,
           31     last_update_preview_attr: TextAttribute,
           32     outline_selection: crate::SelectOutlineDialog,
           33     draw_outline_bg: bool,
           34     opt_cheat_sheet: Option<TextureHandle>,
           35 }
           36 
           37 impl ClipboardHandler for CharFontEditor {
           38     fn can_cut(&self) -> bool {
           39         self.ansi_editor.can_cut()
           40     }
           41     fn cut(&mut self) -> EngineResult<()> {
           42         self.ansi_editor.cut()
           43     }
           44 
           45     fn can_copy(&self) -> bool {
           46         self.ansi_editor.can_copy()
           47     }
           48 
           49     fn copy(&mut self) -> EngineResult<()> {
           50         self.ansi_editor.copy()
           51     }
           52 
           53     fn can_paste(&self) -> bool {
           54         self.ansi_editor.can_paste()
           55     }
           56 
           57     fn paste(&mut self) -> EngineResult<()> {
           58         self.ansi_editor.paste()
           59     }
           60 }
           61 
           62 impl UndoHandler for CharFontEditor {
           63     fn undo_description(&self) -> Option<String> {
           64         self.ansi_editor.undo_description()
           65     }
           66 
           67     fn can_undo(&self) -> bool {
           68         self.ansi_editor.can_undo()
           69     }
           70 
           71     fn undo(&mut self) -> EngineResult<Option<Message>> {
           72         self.ansi_editor.undo()?;
           73         Ok(None)
           74     }
           75 
           76     fn redo_description(&self) -> Option<String> {
           77         self.ansi_editor.redo_description()
           78     }
           79 
           80     fn can_redo(&self) -> bool {
           81         self.ansi_editor.can_redo()
           82     }
           83 
           84     fn redo(&mut self) -> EngineResult<Option<Message>> {
           85         self.ansi_editor.redo()?;
           86         Ok(None)
           87     }
           88 }
           89 
           90 impl Document for CharFontEditor {
           91     fn default_extension(&self) -> &'static str {
           92         "tdf"
           93     }
           94 
           95     fn undo_stack_len(&self) -> usize {
           96         self.undostack_len
           97     }
           98 
           99     fn get_bytes(&mut self, _path: &Path) -> TerminalResult<Vec<u8>> {
          100         self.undostack_len += 1;
          101         self.save_old_selected_char();
          102         TheDrawFont::create_font_bundle(&self.fonts)
          103     }
          104 
          105     fn show_ui(&mut self, ui: &mut egui::Ui, cur_tool: &mut Box<dyn Tool>, selected_tool: usize, options: &DocumentOptions) -> Option<Message> {
          106         SidePanel::left("side_panel").default_width(200.0).show_inside(ui, |ui| {
          107             ui.add_space(4.0);
          108 
          109             if self.selected_font < self.fonts.len() {
          110                 ScrollArea::vertical().show(ui, |ui| {
          111                     ui.style_mut().wrap = Some(false);
          112 
          113                     for i in 0..self.fonts.len() {
          114                         if ui.selectable_value(&mut self.selected_font, i, &self.fonts[i].name).clicked() {
          115                             self.save_old_selected_char();
          116                             self.selected_font = i;
          117                             self.old_selected_char_opt = None;
          118                             self.selected_char_opt = None;
          119                             self.show_selected_char();
          120                         }
          121                     }
          122                 });
          123             }
          124             ui.separator();
          125 
          126             ui.horizontal(|ui| {
          127                 /*if ui.button("+").clicked() {
          128                     self.fonts.push(TheDrawFont::new(
          129                         "New Font",
          130                         icy_engine::FontType::Color,
          131                         1,
          132                     ));
          133                     self.selected_font = self.fonts.len() - 1;
          134                     self.selected_char_opt = None;
          135                     self.old_selected_char_opt = None;
          136                     self.show_selected_char();
          137                     self.undostack_len += 1;
          138                 }*/
          139 
          140                 if ui.add_enabled(self.fonts.len() > 1, Button::new("🗑")).clicked() {
          141                     self.fonts.remove(self.selected_font);
          142                     self.selected_font = 0;
          143                     self.selected_char_opt = None;
          144                     self.old_selected_char_opt = None;
          145                     self.show_selected_char();
          146                     self.undostack_len += 1;
          147                 }
          148 
          149                 if ui.button(fl!(crate::LANGUAGE_LOADER, "tdf-editor-clone_button")).clicked() {
          150                     self.fonts.push(self.fonts[self.selected_font].clone());
          151                     self.selected_font = self.fonts.len() - 1;
          152                     self.selected_char_opt = None;
          153                     self.old_selected_char_opt = None;
          154                     self.show_selected_char();
          155                     self.undostack_len += 1;
          156                 }
          157             });
          158         });
          159 
          160         TopBottomPanel::top("char_top_panel").exact_height(60.).show_inside(ui, |ui| {
          161             ui.add_space(4.0);
          162             if self.selected_font < self.fonts.len() {
          163                 egui::Grid::new(
          164                     "font_grid
          165                     ",
          166                 )
          167                 .num_columns(4)
          168                 .spacing([4.0, 4.0])
          169                 .show(ui, |ui| {
          170                     ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
          171                         ui.label(fl!(crate::LANGUAGE_LOADER, "tdf-editor-font_name_label"));
          172                     });
          173                     if ui
          174                         .add(
          175                             TextEdit::singleline(&mut self.fonts[self.selected_font].name)
          176                                 .min_size(Vec2::new(200.0, 22.))
          177                                 .char_limit(12),
          178                         )
          179                         .changed()
          180                     {
          181                         self.undostack_len += 1;
          182                     }
          183 
          184                     ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
          185                         ui.label(fl!(crate::LANGUAGE_LOADER, "tdf-editor-font_type_label"));
          186                     });
          187 
          188                     let text = match self.fonts[self.selected_font].font_type {
          189                         icy_engine::FontType::Outline => {
          190                             fl!(crate::LANGUAGE_LOADER, "tdf-editor-font_type_outline")
          191                         }
          192                         icy_engine::FontType::Block => {
          193                             fl!(crate::LANGUAGE_LOADER, "tdf-editor-font_type_block")
          194                         }
          195                         icy_engine::FontType::Color => {
          196                             fl!(crate::LANGUAGE_LOADER, "tdf-editor-font_type_color")
          197                         }
          198                     };
          199                     ui.label(text);
          200 
          201                     ui.end_row();
          202                     ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
          203                         ui.label(fl!(crate::LANGUAGE_LOADER, "tdf-editor-spacing_label"));
          204                     });
          205                     if ui
          206                         .add(egui::DragValue::new(&mut self.fonts[self.selected_font].spaces).clamp_range(0.0..=40.0))
          207                         .changed()
          208                     {
          209                         self.undostack_len += 1;
          210                     }
          211                     ui.label("");
          212                     ui.label("");
          213                     ui.end_row();
          214                 });
          215             } else {
          216                 ui.heading(fl!(crate::LANGUAGE_LOADER, "tdf-editor-no_font_selected_label"));
          217             }
          218         });
          219 
          220         TopBottomPanel::bottom("char_bottom_panel").exact_height(150.).show_inside(ui, |ui| {
          221             if self.selected_font < self.fonts.len() {
          222                 self.show_char_selector(ui);
          223                 ui.add_space(4.0);
          224                 if self.selected_char_opt.is_some() && ui.button(fl!(crate::LANGUAGE_LOADER, "tdf-editor-clear_char_button")).clicked() {
          225                     self.fonts[self.selected_font].clear_glyph(self.selected_char_opt.unwrap());
          226                     self.selected_char_opt = None;
          227                     self.old_selected_char_opt = None;
          228                     self.show_selected_char();
          229                     self.undostack_len += 1;
          230                 }
          231             }
          232         });
          233 
          234         egui::CentralPanel::default().show_inside(ui, |ui| {
          235             if self.selected_font < self.fonts.len() {
          236                 let attr = self
          237                     .ansi_editor
          238                     .buffer_view
          239                     .lock()
          240                     .get_edit_state()
          241                     .get_caret()
          242                     .get_attribute();
          243 
          244                 let mut is_outline = false;
          245                 for layer in &mut self
          246                 .ansi_editor
          247                     .buffer_view
          248                     .lock()
          249                     .get_edit_state_mut()
          250                     .get_buffer_mut()
          251                     .layers
          252                 {
          253                     match self.fonts[self.selected_font].font_type {
          254                         icy_engine::FontType::Outline => {
          255                             is_outline = true;
          256                             set_attribute(layer, attr);
          257                         }
          258                         icy_engine::FontType::Block => {
          259                             set_attribute(layer, attr);
          260                         }
          261                         icy_engine::FontType::Color => {
          262                         }
          263                     }
          264                 }
          265 
          266                 if is_outline {
          267                     SidePanel::right("outline…_side_panel")
          268                         .default_width(290.)
          269                         .show_inside(ui, |ui| {
          270                             TopBottomPanel::bottom("outline_style_bottom_panel")
          271                                 .exact_height(220.)
          272                                 .show_inside(ui, |ui| {
          273                                     self.outline_selection.show_outline_ui(ui, 8, Vec2::new(4.0, 4.0));
          274                                     let outline_style = self.outline_selection.get_outline_style();
          275                                     let old_style = self.outline_previewbuffer_view.lock().get_edit_state_mut().get_outline_style();
          276                                     self.outline_previewbuffer_view.lock().get_edit_state_mut().set_outline_style(outline_style);
          277                                     if outline_style != old_style {
          278                                         self.show_selected_char();
          279                                     }
          280                                 });
          281 
          282                                 let opt = icy_engine_egui::TerminalOptions {
          283                                     stick_to_bottom: false,
          284                                     scale: Some(Vec2::new(2.0, 2.0)),
          285                                     monitor_settings: unsafe { SETTINGS.monitor_settings.clone() },
          286                                     marker_settings: unsafe { SETTINGS.marker_settings.clone() },
          287                                     id: Some(egui::Id::new(self.id + 20000)),
          288                                     ..Default::default()
          289                                 };
          290 
          291                             self.outline_previewbuffer_view
          292                                 .lock()
          293                                 .get_caret_mut()
          294                                 .set_is_visible(false);
          295                             ui.horizontal(|ui|  {
          296                                 ui.label(fl!(crate::LANGUAGE_LOADER, "tdf-editor-outline_preview_label"));
          297                                 ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
          298                                     if ui.checkbox(&mut self.draw_outline_bg, fl!(crate::LANGUAGE_LOADER, "tdf-editor-draw_bg_checkbox")).changed() {
          299                                         self.render_outline_preview();
          300                                     }
          301                                 });
          302                             });
          303                             let (_, _) = show_terminal_area(
          304                                 ui,
          305                                 self.outline_previewbuffer_view.clone(),
          306                                 opt,
          307                             );
          308                         });
          309 
          310 
          311                     TopBottomPanel::top("cheat_sheet_top_panel")
          312                     .exact_height(50.)
          313                     .show_inside(ui, |ui| {
          314                         if self.opt_cheat_sheet.is_none() {
          315 
          316                             let mut key = fl!(crate::LANGUAGE_LOADER, "tdf-editor-cheat_sheet_key");
          317                             let mut code = fl!(crate::LANGUAGE_LOADER, "tdf-editor-cheat_sheet_code");
          318                             let mut res = fl!(crate::LANGUAGE_LOADER, "tdf-editor-cheat_sheet_res");
          319 
          320                              let m = key.len().max(code.len()).max(res.len());
          321                              let mut buffer = Buffer::new((56 + m, 3));
          322                              while key.len() < m {
          323                                 key.insert(0, ' ');
          324                              }
          325                              while code.len() < m {
          326                                 code.insert(0, ' ');
          327                              }
          328                              while res.len() < m {
          329                                 res.insert(0, ' ');
          330                              }
          331 
          332                             let s  = format!("{key}: F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 1  2  3  4  5  6  7  8 ");
          333                             let s2 = format!("{code}: A  B  C  D  E  F  G  H  I  J   K  L  M  N  O  @  &  \u{F7} ");
          334                             let s3 = format!("{res}: \u{CD}  \u{C4}  \u{B3}  \u{BA}  \u{D5}  \u{BB}  \u{D5}  \u{BF}  \u{C8}  \u{BE}   \u{C0}  \u{BD}  \u{B5}  \u{C7}  SP    &  \u{F7}");
          335 
          336                             let mut attr  = TextAttribute::default();
          337                             attr.set_foreground(0);
          338                             attr.set_background(4);
          339 
          340                             for (i, c) in s.chars().enumerate() {
          341                                 buffer.layers[0].set_char((i, 0), AttributedChar::new(c, attr));
          342                             }
          343 
          344                             attr.set_foreground(15);
          345                             attr.set_background(4);
          346 
          347                             for (i, c) in s2.chars().enumerate() {
          348                                 buffer.layers[0].set_char((i, 1), AttributedChar::new(c, attr));
          349                             }
          350                             attr.set_foreground(14);
          351                             attr.set_background(0);
          352 
          353                             for (i, c) in s3.chars().enumerate() {
          354                                 buffer.layers[0].set_char((i, 2), AttributedChar::new(c, attr));
          355                             }
          356                             self.opt_cheat_sheet = Some(crate::create_image(ui.ctx(),&buffer));
          357                         }
          358 
          359                         if let Some(image) = & self.opt_cheat_sheet {
          360                             ui.vertical_centered(|ui| {
          361                                 let sized_texture:SizedTexture = (image).into();
          362                                 let image = Image::from_texture(sized_texture);
          363                                 let mut size = sized_texture.size;
          364                                 let width = ui.available_width();
          365                                 if width < size.x {
          366                                     size.y *= width / size.x;
          367                                     size.x = width;
          368                                 }
          369                                 let r = Rect::from_min_size(
          370                                     ui.min_rect().min,
          371                                     size,
          372                                 );
          373                                 image.paint_at(ui, r);
          374 
          375                             });
          376                         }
          377                     });
          378 
          379                     egui::CentralPanel::default().show_inside(ui, |ui| {
          380                         self.ansi_editor
          381                             .show_ui(ui, cur_tool, selected_tool, options);
          382                     });
          383                 } else {
          384                     self.ansi_editor
          385                         .show_ui(ui, cur_tool, selected_tool, options);
          386                 }
          387             }
          388         });
          389         let u = self.ansi_editor.buffer_view.lock().get_edit_state().undo_stack_len();
          390         let attr = self.ansi_editor.buffer_view.lock().get_edit_state().get_caret().get_attribute();
          391         if self.last_update_preview != u || self.last_update_preview_attr != attr {
          392             self.last_update_preview = u;
          393             self.last_update_preview_attr = attr;
          394             self.save_old_selected_char();
          395             self.render_outline_preview();
          396         }
          397 
          398         None
          399     }
          400 
          401     fn get_ansi_editor_mut(&mut self) -> Option<&mut AnsiEditor> {
          402         self.ansi_editor.get_ansi_editor_mut()
          403     }
          404 
          405     fn get_ansi_editor(&self) -> Option<&AnsiEditor> {
          406         self.ansi_editor.get_ansi_editor()
          407     }
          408 
          409     fn destroy(&self, gl: &glow::Context) -> Option<Message> {
          410         self.ansi_editor.destroy(gl);
          411         None
          412     }
          413 }
          414 
          415 fn set_attribute(layer: &mut Layer, attr: TextAttribute) {
          416     for y in 0..layer.get_size().height {
          417         for x in 0..layer.get_size().width {
          418             let mut c = layer.get_char((x, y));
          419             if !c.is_visible() {
          420                 continue;
          421             }
          422             c.attribute = attr;
          423             layer.set_char((x, y), c);
          424         }
          425     }
          426 }
          427 
          428 impl CharFontEditor {
          429     pub fn new(gl: &Arc<glow::Context>, id: usize, fonts: Vec<TheDrawFont>) -> Self {
          430         let mut buffer = Buffer::new(Size::new(30, 12));
          431         set_up_layers(&mut buffer);
          432         let ansi_editor = AnsiEditor::new(gl, id, buffer);
          433 
          434         let mut buffer = Buffer::new(Size::new(30, 12));
          435         buffer.is_terminal_buffer = false;
          436         let mut buffer_view = BufferView::from_buffer(gl, buffer);
          437         buffer_view.interactive = false;
          438         let outline_previewbuffer_view = Arc::new(Mutex::new(buffer_view));
          439 
          440         let mut res = Self {
          441             id,
          442             font: BitFont::default(),
          443             ansi_editor,
          444             selected_char_opt: Some('A'),
          445             old_selected_char_opt: None,
          446             fonts,
          447             selected_font: 0,
          448             undostack_len: 0,
          449             outline_previewbuffer_view,
          450             outline_selection: SelectOutlineDialog::default(),
          451             last_update_preview: 0,
          452             opt_cheat_sheet: None,
          453             draw_outline_bg: true,
          454             last_update_preview_attr: TextAttribute::default(),
          455         };
          456         res.show_selected_char();
          457         res
          458     }
          459 
          460     pub fn show_char_selector(&mut self, ui: &mut egui::Ui) {
          461         egui::ScrollArea::vertical().show(ui, |ui| {
          462             ui.horizontal_wrapped(|ui| {
          463                 ui.spacing_mut().item_spacing = egui::Vec2::new(0., 0.);
          464                 for i in b'!'..=b'~' {
          465                     let ch = unsafe { char::from_u32_unchecked(i as u32) };
          466                     let mut style = DrawGlyphStyle::Normal;
          467                     if !self.fonts[self.selected_font].has_char(i) {
          468                         style = DrawGlyphStyle::GrayOut
          469                     }
          470                     if let Some(ch2) = self.selected_char_opt {
          471                         if ch == ch2 {
          472                             style = DrawGlyphStyle::Selected
          473                         }
          474                     }
          475                     let response = BitFontEditor::draw_glyph(ui, &self.font, style, ch);
          476                     if response.clicked() {
          477                         self.selected_char_opt = Some(ch);
          478                         self.show_selected_char();
          479                     }
          480                 }
          481             });
          482         });
          483     }
          484 
          485     fn render_outline_preview(&mut self) {
          486         let font = &self.fonts[self.selected_font];
          487         if matches!(font.font_type, icy_engine::FontType::Outline) {
          488             let lock = &mut self.ansi_editor.buffer_view.lock();
          489             let mut attr = lock.get_caret().get_attribute();
          490 
          491             let _ = self.outline_previewbuffer_view.lock().get_edit_state_mut().clear_layer(0);
          492             self.outline_previewbuffer_view.lock().get_caret_mut().set_attr(attr);
          493             if let Some(ch) = self.selected_char_opt {
          494                 let size = self.outline_previewbuffer_view.lock().get_edit_state_mut().get_buffer().get_size();
          495 
          496                 if self.draw_outline_bg {
          497                     attr.set_foreground(8);
          498                     attr.set_background(0);
          499                     for y in 0..size.height {
          500                         for x in 0..size.width {
          501                             self.outline_previewbuffer_view.lock().get_edit_state_mut().get_buffer_mut().layers[0]
          502                                 .set_char((x, y), AttributedChar::new('\u{B1}', attr));
          503                         }
          504                     }
          505                 }
          506 
          507                 font.render(self.outline_previewbuffer_view.lock().get_edit_state_mut(), ch as u8);
          508             }
          509         }
          510     }
          511 
          512     fn show_selected_char(&mut self) {
          513         {
          514             self.save_old_selected_char();
          515             let font = &self.fonts[self.selected_font];
          516             self.ansi_editor.outline_font_mode = matches!(font.font_type, icy_engine::FontType::Outline);
          517             let lock = &mut self.ansi_editor.buffer_view.lock();
          518 
          519             let edit_state = &mut lock.get_edit_state_mut();
          520             set_up_layers(edit_state.get_buffer_mut());
          521             edit_state.set_current_layer(1);
          522             edit_state.get_caret_mut().set_position((0, 0).into());
          523             edit_state.set_outline_style(usize::MAX);
          524 
          525             if let Some(ch) = self.selected_char_opt {
          526                 font.render(edit_state, ch as u8);
          527             }
          528 
          529             edit_state.get_undo_stack().lock().unwrap().clear();
          530             self.old_selected_char_opt = self.selected_char_opt;
          531         }
          532         self.render_outline_preview();
          533     }
          534 
          535     fn save_old_selected_char(&mut self) {
          536         if self.ansi_editor.buffer_view.lock().get_edit_state().undo_stack_len() == 0 {
          537             return;
          538         }
          539         self.undostack_len += 1;
          540         if let Some(font) = self.fonts.get_mut(self.selected_font) {
          541             if let Some(ch) = self.old_selected_char_opt {
          542                 match font.font_type {
          543                     icy_engine::FontType::Outline => {
          544                         let lock = &mut self.ansi_editor.buffer_view.lock();
          545                         let buf = lock.get_buffer();
          546                         let mut data = Vec::new();
          547                         let mut w = 0;
          548                         let mut h = 0;
          549                         for y in 0..buf.get_line_count() {
          550                             if y > 0 {
          551                                 data.push(13);
          552                             }
          553                             let lw = buf.get_line_length(y);
          554                             for x in 0..lw {
          555                                 let ch = buf.get_char((x, y));
          556                                 if VALID_OUTLINE_CHARS.contains(ch.ch) {
          557                                     data.push(ch.ch as u8);
          558                                 }
          559                             }
          560                             w = w.max(lw);
          561                             h = y;
          562                         }
          563 
          564                         font.set_glyph(ch, FontGlyph { size: Size::new(w, h), data });
          565                     }
          566                     icy_engine::FontType::Block => {
          567                         let lock = &mut self.ansi_editor.buffer_view.lock();
          568                         let buf = lock.get_buffer();
          569                         let mut data = Vec::new();
          570                         let mut w = 0;
          571                         let mut h = 0;
          572                         for y in 0..buf.get_line_count() {
          573                             if y > 0 {
          574                                 data.push(13);
          575                             }
          576                             let lw = buf.get_line_length(y);
          577                             for x in 0..lw {
          578                                 let ch = buf.get_char((x, y));
          579                                 data.push(ch.ch as u8);
          580                             }
          581                             w = w.max(lw);
          582                             h = y;
          583                         }
          584 
          585                         font.set_glyph(ch, FontGlyph { size: Size::new(w, h), data });
          586                     }
          587                     icy_engine::FontType::Color => {
          588                         let lock = &mut self.ansi_editor.buffer_view.lock();
          589                         let buf = lock.get_buffer();
          590                         let mut data = Vec::new();
          591                         let mut w = 0;
          592                         let mut h = 0;
          593                         for y in 0..buf.get_line_count() {
          594                             if y > 0 {
          595                                 data.push(13);
          596                             }
          597                             let lw = buf.get_line_length(y);
          598                             for x in 0..lw {
          599                                 let ch = buf.get_char((x, y));
          600                                 data.push(ch.ch as u8);
          601                                 data.push(ch.attribute.as_u8(icy_engine::IceMode::Ice));
          602                             }
          603                             w = w.max(lw);
          604                             h = y;
          605                         }
          606 
          607                         font.set_glyph(ch, FontGlyph { size: Size::new(w, h), data });
          608                     }
          609                 }
          610             }
          611         }
          612     }
          613 }
          614 
          615 fn set_up_layers(buffer: &mut Buffer) {
          616     buffer.layers.clear();
          617 
          618     let mut new_layer = Layer::new("background", Size::new(30, 12));
          619     new_layer.properties.has_alpha_channel = false;
          620     new_layer.properties.is_locked = true;
          621     new_layer.properties.is_position_locked = true;
          622     buffer.layers.push(new_layer);
          623 
          624     let mut new_layer = Layer::new("edit layer", Size::new(30, 12));
          625     new_layer.properties.has_alpha_channel = true;
          626     new_layer.properties.is_position_locked = true;
          627     buffer.layers.push(new_layer);
          628 }