Itemizer
This commit is contained in:
		
							parent
							
								
									aad5dc2112
								
							
						
					
					
						commit
						17063d5216
					
				
							
								
								
									
										37
									
								
								src/render/context.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/render/context.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | |||||||
|  | use std::ffi::CString; | ||||||
|  | 
 | ||||||
|  | use pangocairo::FontMap; | ||||||
|  | use pango::prelude::*; | ||||||
|  | use pango; | ||||||
|  | 
 | ||||||
|  | use sys::pango::*; | ||||||
|  | 
 | ||||||
|  | use ui_model::StyledLine; | ||||||
|  | 
 | ||||||
|  | pub struct Context { | ||||||
|  |     pango_context: pango::Context, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Context { | ||||||
|  |     pub fn new(font_desc: &pango::FontDescription) -> Self { | ||||||
|  |         Context { 
 | ||||||
|  |             pango_context: create_pango_context(font_desc), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn update(&mut self, font_desc: &pango::FontDescription) { | ||||||
|  |         self.pango_context = create_pango_context(font_desc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn itemize(&self, line: &StyledLine)-> Vec<item::Item> { | ||||||
|  |         pango_itemize(&self.pango_context, &line.line_str, &line.attr_list) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn create_pango_context(font_desc: &pango::FontDescription) -> pango::Context { | ||||||
|  |     let font_map = FontMap::get_default(); | ||||||
|  |     let pango_context = font_map.create_context().unwrap(); | ||||||
|  |     pango_context.set_font_description(&font_desc); | ||||||
|  | 
 | ||||||
|  |     pango_context | ||||||
|  | } | ||||||
| @ -1,28 +1,30 @@ | |||||||
|  | mod context; | ||||||
|  | 
 | ||||||
| use sys::pango::*; | use sys::pango::*; | ||||||
| use pango; | use pango; | ||||||
| use pango::prelude::*; | use pango::prelude::*; | ||||||
| use cairo; | use cairo; | ||||||
| use pangocairo::{CairoContextExt, FontMap}; | use pangocairo::{CairoContextExt, FontMap}; | ||||||
| use std::ffi::CString; | use std::ffi::CString; | ||||||
|  | use ui_model; | ||||||
| 
 | 
 | ||||||
| pub fn render(ctx: &cairo::Context, font_desc: pango::FontDescription) { | pub fn render(ctx: &cairo::Context, font_desc: pango::FontDescription) { | ||||||
|     let font_map = FontMap::get_default(); |     let font_map = FontMap::get_default(); | ||||||
|     let pango_context = font_map.create_context().unwrap(); |     let pango_context = font_map.create_context().unwrap(); | ||||||
|     pango_context.set_font_description(&font_desc); |     pango_context.set_font_description(&font_desc); | ||||||
| 
 | 
 | ||||||
|     let text = "TEST String".to_owned().into_bytes(); |     let text = "TEST String".to_owned(); | ||||||
|     let len = text.len(); |  | ||||||
|     let text = CString::new(text).unwrap(); |  | ||||||
|     let attr_list = pango::AttrList::new(); |     let attr_list = pango::AttrList::new(); | ||||||
| 
 | 
 | ||||||
|     ctx.move_to(0.0, 50.0); |     ctx.move_to(0.0, 50.0); | ||||||
|     let items = pango_itemize(&pango_context, &text, 0, len, &attr_list); |     let items = pango_itemize(&pango_context, &text, &attr_list); | ||||||
|     for item in items { |     for item in items { | ||||||
|         let mut glyphs = pango::GlyphString::new(); |         let mut glyphs = pango::GlyphString::new(); | ||||||
|         let analysis = item.analysis(); |         let analysis = item.analysis(); | ||||||
|         pango_shape(&text, len, &analysis, &mut glyphs); |         pango_shape(&text, &analysis, &mut glyphs); | ||||||
|         let font = analysis.font(); |         let font = analysis.font(); | ||||||
|         let (ink, logical) = glyphs.extents(&font); |         let (ink, logical) = glyphs.extents(&font); | ||||||
|         ctx.show_glyph_string(&font, &glyphs); |         ctx.show_glyph_string(&font, &glyphs); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| mod item; | pub mod item; | ||||||
| mod analysis; | mod analysis; | ||||||
| 
 | 
 | ||||||
| use std::ptr; | use std::ptr; | ||||||
| @ -11,17 +11,15 @@ use glib::translate::*; | |||||||
| 
 | 
 | ||||||
| pub fn pango_itemize( | pub fn pango_itemize( | ||||||
|     context: &pango::Context, |     context: &pango::Context, | ||||||
|     text: &CStr, |     text: &String, | ||||||
|     start_index: usize, |     attrs: &pango::AttrList | ||||||
|     length: usize, |  | ||||||
|     attrs: &pango::AttrList, |  | ||||||
| ) -> Vec<item::Item> { | ) -> Vec<item::Item> { | ||||||
|     unsafe { |     unsafe { | ||||||
|         FromGlibPtrContainer::from_glib_container(pango_sys::pango_itemize( |         FromGlibPtrContainer::from_glib_container(pango_sys::pango_itemize( | ||||||
|             context.to_glib_none().0, |             context.to_glib_none().0, | ||||||
|             text.as_ptr(), |             text.as_ptr() as *const i8, | ||||||
|             start_index as i32, |             0, | ||||||
|             length as i32, |             text.len() as i32, | ||||||
|             attrs.to_glib_none().0, |             attrs.to_glib_none().0, | ||||||
|             ptr::null_mut(), |             ptr::null_mut(), | ||||||
|         )) |         )) | ||||||
| @ -29,15 +27,14 @@ pub fn pango_itemize( | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn pango_shape( | pub fn pango_shape( | ||||||
|     text: &CStr, |     text: &String, | ||||||
|     length: usize, |  | ||||||
|     analysis: &analysis::Analysis, |     analysis: &analysis::Analysis, | ||||||
|     glyphs: &mut pango::GlyphString, |     glyphs: &mut pango::GlyphString, | ||||||
| ) { | ) { | ||||||
|     unsafe { |     unsafe { | ||||||
|         pango_sys::pango_shape( |         pango_sys::pango_shape( | ||||||
|             text.as_ptr(), |             text.as_ptr() as *const i8, | ||||||
|             length as i32, |             text.len() as i32, | ||||||
|             analysis.to_glib_ptr(), |             analysis.to_glib_ptr(), | ||||||
|             glyphs.to_glib_none_mut().0, |             glyphs.to_glib_none_mut().0, | ||||||
|         ); |         ); | ||||||
|  | |||||||
| @ -1,23 +1,113 @@ | |||||||
|  | use std::ops::{Index, IndexMut}; | ||||||
|  | 
 | ||||||
| use super::cell::Cell; | use super::cell::Cell; | ||||||
| use pango::Item; | use pango; | ||||||
|  | 
 | ||||||
|  | pub struct Item { | ||||||
|  |     item: pango::Item, | ||||||
|  |     glyph_string: Option<pango::GlyphString>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Item { | ||||||
|  |     pub fn new(item: pango::Item) -> Self { | ||||||
|  |         Item { | ||||||
|  |             item, | ||||||
|  |             glyph_string: None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| pub struct Line { | pub struct Line { | ||||||
|     line: Box<[Cell]>, |     pub line: Box<[Cell]>, | ||||||
|     item_line: Option<Box<[Item]>>, |     item_line: Option<Box<[Item]>>, | ||||||
|     cell_to_item: Box<[usize]>, |     cell_to_item: Box<[usize]>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Line { | impl Line { | ||||||
|     pub fn new(columns: usize) -> Self { |     pub fn new(columns: usize) -> Self { | ||||||
|         let line = Vec::with_capacity(columns); |         let mut line = Vec::with_capacity(columns); | ||||||
|         for _ in 0..columns { |         for _ in 0..columns { | ||||||
|             line.push(Cell::new(' ')); |             line.push(Cell::new(' ')); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         Line { 
 |         Line { | ||||||
|             cell_to_item: Vec::with_capacity(line.len()).into_boxed_slice(), |             cell_to_item: Vec::with_capacity(line.len()).into_boxed_slice(), | ||||||
|             line: line.into_boxed_slice(), |             line: line.into_boxed_slice(), | ||||||
|             item_line: None, |             item_line: None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn clear(&mut self, left: usize, right: usize) { | ||||||
|  |         for cell in &mut self.line[left..right + 1] { | ||||||
|  |             cell.clear(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Index<usize> for Line { | ||||||
|  |     type Output = Cell; | ||||||
|  | 
 | ||||||
|  |     fn index(&self, index: usize) -> &Cell { | ||||||
|  |         &self.line[index] | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl IndexMut<usize> for Line { | ||||||
|  |     fn index_mut(&mut self, index: usize) -> &mut Cell { | ||||||
|  |         &mut self.line[index] | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub struct StyledLine { | ||||||
|  |     pub line_str: String, | ||||||
|  |     cell_to_byte: Box<[usize]>, | ||||||
|  |     pub attr_list: pango::AttrList, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl StyledLine { | ||||||
|  |     pub fn from(line: &Line) -> Self { | ||||||
|  |         let mut line_str = String::new(); | ||||||
|  |         let mut cell_to_byte = Vec::new(); | ||||||
|  |         let attr_list = pango::AttrList::new(); | ||||||
|  |         let mut byte_offset = 0; | ||||||
|  | 
 | ||||||
|  |         for (cell_idx, cell) in line.line.iter().enumerate() { | ||||||
|  |             if cell.attrs.double_width { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             line_str.push(cell.ch); | ||||||
|  |             let len = line_str.len(); | ||||||
|  | 
 | ||||||
|  |             for i in byte_offset..byte_offset + len { | ||||||
|  |                 cell_to_byte.push(cell_idx); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             insert_attrs(cell, &attr_list, byte_offset as u32, (byte_offset + len) as u32); | ||||||
|  | 
 | ||||||
|  |             byte_offset += len; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         StyledLine { | ||||||
|  |             line_str, | ||||||
|  |             cell_to_byte: cell_to_byte.into_boxed_slice(), | ||||||
|  |             attr_list, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn insert_attrs(cell: &Cell, attr_list: &pango::AttrList, start_idx: u32, end_idx: u32) { | ||||||
|  |     if cell.attrs.italic { | ||||||
|  |         let mut attr = pango::Attribute::new_style(pango::Style::Italic).unwrap(); | ||||||
|  |         attr.set_start_index(start_idx); | ||||||
|  |         attr.set_end_index(end_idx); | ||||||
|  |         attr_list.insert(attr); | ||||||
|  |     } | ||||||
|  |     if cell.attrs.bold { | ||||||
|  |         let mut attr = pango::Attribute::new_weight(pango::Weight::Bold).unwrap(); | ||||||
|  |         attr.set_start_index(start_idx); | ||||||
|  |         attr.set_end_index(end_idx); | ||||||
|  |         attr_list.insert(attr); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ mod cell; | |||||||
| mod line; | mod line; | ||||||
| 
 | 
 | ||||||
| pub use self::cell::{Cell, Attrs}; | pub use self::cell::{Cell, Attrs}; | ||||||
|  | pub use self::line::{Item, StyledLine}; | ||||||
| use self::line::Line; | use self::line::Line; | ||||||
| 
 | 
 | ||||||
| use std::slice::Iter; | use std::slice::Iter; | ||||||
| @ -158,9 +159,7 @@ impl UiModel { | |||||||
| 
 | 
 | ||||||
|     fn clear_region(&mut self, top: usize, bot: usize, left: usize, right: usize) { |     fn clear_region(&mut self, top: usize, bot: usize, left: usize, right: usize) { | ||||||
|         for row in &mut self.model[top..bot + 1] { |         for row in &mut self.model[top..bot + 1] { | ||||||
|             for cell in &mut row[left..right + 1] { |             row.clear(left, right); | ||||||
|                 cell.clear(); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -321,7 +320,7 @@ impl AsRef<ModelRect> for ModelRect { | |||||||
| pub struct ClipRowIterator<'a> { | pub struct ClipRowIterator<'a> { | ||||||
|     rect: &'a ModelRect, |     rect: &'a ModelRect, | ||||||
|     pos: usize, |     pos: usize, | ||||||
|     iter: Iter<'a, Vec<Cell>>, |     iter: Iter<'a, Line>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'a> ClipRowIterator<'a> { | impl<'a> ClipRowIterator<'a> { | ||||||
| @ -347,11 +346,11 @@ impl<'a> Iterator for ClipRowIterator<'a> { | |||||||
| 
 | 
 | ||||||
| pub struct ClipLine<'a> { | pub struct ClipLine<'a> { | ||||||
|     rect: &'a ModelRect, |     rect: &'a ModelRect, | ||||||
|     line: &'a [Cell], |     line: &'a Line, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'a> ClipLine<'a> { | impl<'a> ClipLine<'a> { | ||||||
|     pub fn new(model: &'a [Cell], rect: &'a ModelRect) -> ClipLine<'a> { |     pub fn new(model: &'a Line, rect: &'a ModelRect) -> ClipLine<'a> { | ||||||
|         ClipLine { |         ClipLine { | ||||||
|             line: model, |             line: model, | ||||||
|             rect: rect, |             rect: rect, | ||||||
| @ -366,7 +365,7 @@ impl<'a> ClipLine<'a> { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn get(&self, idx: usize) -> Option<&Cell> { |     pub fn get(&self, idx: usize) -> Option<&Cell> { | ||||||
|         self.line.get(idx) |         self.line.line.get(idx) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn iter(&self) -> ClipColIterator<'a> { |     pub fn iter(&self) -> ClipColIterator<'a> { | ||||||
| @ -381,11 +380,11 @@ pub struct ClipColIterator<'a> { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'a> ClipColIterator<'a> { | impl<'a> ClipColIterator<'a> { | ||||||
|     pub fn new(model: &'a [Cell], rect: &'a ModelRect) -> ClipColIterator<'a> { |     pub fn new(model: &'a Line, rect: &'a ModelRect) -> ClipColIterator<'a> { | ||||||
|         ClipColIterator { |         ClipColIterator { | ||||||
|             rect: rect, |             rect: rect, | ||||||
|             pos: 0, |             pos: 0, | ||||||
|             iter: model[rect.left..rect.right + 1].iter(), |             iter: model.line[rect.left..rect.right + 1].iter(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 daa84
						daa84