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