% jwilm@kurast.local ➜  ~/code/alacritty  [?1h=[?2004h bck-i-search: _mv ../../../{grid.json,size.json,alacritty.recording} ./v_cd vim_large_window_scroll i_imm_     vvivim ssrrcc//rreenndderer/r [?1l>[?2004l [?1049h[?1h=▽ [?12;25h[?12l[?25h[?25l"src/renderer" is a directory[>c" ============================================================================   " Netrw Directory Listing (netrw v156)   " /Users/jwilm/code/alacritty/src/renderer  " Sorted by name  " Sort sequence: [\/]$,\,\.h$,\.c$,\.cpp$,\~\=\*$,*,\.o$,\.obj$,\.info$,\.swp$,\.bak$,\~$ " Quick Help: :help -:go up dir D:delete R:rename s:sort-by x:special  " ==============================================================================  ../ ./  mod.rs  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 8,1All[?12l[?25h[?25l../ ./ 9[?12l[?25h[?25l./ mod.rs 10,1[?12l[?25h[?25l~/code/alacritty/src/renderer/mod.rs"1354L, 40527C 864  }    865     866  pub fn deactivate(&self) {     867  unsafe {     868  gl::UseProgram(0);   869  }    870  }    871     872  pub fn new(    873  config: &Config,  874 size: Size<Pixels<u32>>   875 ) -> Result<ShaderProgram, ShaderCreationError> {   876 let vertex_source = if cfg!(feature = "live-shader-reload") {   877 None   878 } else {   879 Some(TEXT_SHADER_V)   880 };   881 let vertex_shader = ShaderProgram::create_shader(   882 TEXT_SHADER_V_PATH,   883 gl::VERTEX_SHADER,   884 vertex_source   885 )?;   886 let frag_source = if cfg!(feature = "live-shader-reload") {   887 None   888 } else {   889 Some(TEXT_SHADER_F)   890 };   891 let fragment_shader = ShaderProgram::create_shader(   892 TEXT_SHADER_F_PATH,   893 gl::FRAGMENT_SHADER,   894 frag_source   895 )?;   896 let program = ShaderProgram::create_program(vertex_shader, fragment_shader);   897   898 unsafe {   899 gl::DeleteShader(vertex_shader);   900 gl::DeleteShader(fragment_shader);   901 gl::UseProgram(program);   902 }   903   904 macro_rules! cptr {   905 ($thing:expr) => { $thing.as_ptr() as *const _ }   906 }   907   908 macro_rules! assert_uniform_valid {   909 ($uniform:expr) => {   910 assert!($uniform != gl::INVALID_VALUE as i32);   911 assert!($uniform != gl::INVALID_OPERATION as i32);   912 };   913 ( $( $uniform:expr ),* ) => {   914 $( assert_uniform_valid!($uniform); )*   915 };   916 }   917   918 // get uniform locations   919 let (projection, term_dim, cell_dim, visual_bell, background) = unsafe {  891,166%[?12l[?25h[?25l 1 // Copyright 2016 Joe Wilm, The Alacritty Project Contributors   2 //   3 // Licensed under the Apache License, Version 2.0 (the "License");   4 // you may not use this file except in compliance with the License.   5 // You may obtain a copy of the License at   6 //   7 // http://www.apache.org/licenses/LICENSE-2.0   8 //   9 // Unless required by applicable law or agreed to in writing, software   10 // distributed under the License is distributed on an "AS IS" BASIS,   11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   12 // See the License for the specific language governing permissions and   13 // limitations under the License.   14 use std::collections::HashMap;   15 use std::hash::BuildHasherDefault;   16 use std::fs::File;   17 use std::io::{self, Read};   18 use std::mem::size_of;   19 use std::path::{PathBuf};   20 use std::ptr;   21 use std::sync::mpsc;   22    23 use cgmath;   24 use fnv::FnvHasher;   25 use font::{self, Rasterizer, Rasterize, RasterizedGlyph, FontDesc, GlyphKey, FontKey};   26 use gl::types::*;   27 use gl;   28 use index::{Line, Column, RangeInclusive};   29 use notify::{Watcher as WatcherApi, RecommendedWatcher as Watcher, op};   30    31 use config::{self, Config, Delta};   32 use term::{self, cell, RenderableCell};   33 use window::{Size, Pixels};   34    35 use Rgb;   36    37 // Shader paths for live reload   38 static TEXT_SHADER_F_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl");    39 static TEXT_SHADER_V_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl");    40    41 // Shader source which is used when live-shader-reload feature is disable   42 static TEXT_SHADER_F: &'static str = include_str!(   43  concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl")   44 );   45 static TEXT_SHADER_V: &'static str = include_str!(   46  concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl")   47 );   48    49 /// `LoadGlyph` allows for copying a rasterized glyph into graphics memory   50 pub trait LoadGlyph {   51  /// Load the rasterized glyph into GPU memory   52  fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph;   53 }   54    55 enum Msg {   56  ShaderReload, 1,1Top[?12l[?25h[?25l:[?12l[?25hs[?25l[?12l[?25he[?25l[?12l[?25ht[?25l[?12l[?25h[?25l ft=yaml[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25hc[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25hc[?25l[?12l[?25ho[?25l[?12l[?25hl[?25l[?12l[?25ho[?25l[?12l[?25hr[?25l[?12l[?25hs[?25l[?12l[?25hh[?25l[?12l[?25h[?25l[?12l[?25hc[?25l[?12l[?25hh[?25l[?12l[?25he[?25l[?12l[?25hm[?25l[?12l[?25he[?25l[?12l[?25h[?25l [?12l[?25h...[?25lTomorrow-Night-Bright[?12l[?25h...[?25lblue[?12l[?25h...[?25ldarkblue[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25h[?25l[?12l[?25ht[?25l[?12l[?25h...[?25lTomorrow-Night-Bright[?12l[?25h...[?25ltende[?12l[?25h [?25l 1 // Copyright 2016 Joe Wilm, The Alacritty Project Contributors   2 //   3 // Licensed under the Apache License, Version 2.0 (the "License");   4 // you may not use this file except in compliance with the License.   5 // You may obtain a copy of the License at   6 //   7 // http://www.apache.org/licenses/LICENSE-2.0   8 //   9 // Unless required by applicable law or agreed to in writing, software   10 // distributed under the License is distributed on an "AS IS" BASIS,   11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   12 // See the License for the specific language governing permissions and   13 // limitations under the License.   14 use std::collections::HashMap;   15 use std::hash::BuildHasherDefault;   16 use std::fs::File;   17 use std::io::{self, Read};   18 use std::mem::size_of;   19 use std::path::{PathBuf};   20 use std::ptr;   21 use std::sync::mpsc;   22    23 use cgmath;   24 use fnv::FnvHasher;   25 use font::{self, Rasterizer, Rasterize, RasterizedGlyph, FontDesc, GlyphKey, FontKey};   26 use gl::types::*;   27 use gl;   28 use index::{Line, Column, RangeInclusive};   29 use notify::{Watcher as WatcherApi, RecommendedWatcher as Watcher, op};   30    31 use config::{self, Config, Delta};   32 use term::{self, cell, RenderableCell};   33 use window::{Size, Pixels};   34    35 use Rgb;   36    37 // Shader paths for live reload   38 static TEXT_SHADER_F_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl");    39 static TEXT_SHADER_V_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl");    40    41 // Shader source which is used when live-shader-reload feature is disable   42 static TEXT_SHADER_F: &'static str = include_str!(   43  concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl")   44 );   45 static TEXT_SHADER_V: &'static str = include_str!(   46  concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl")   47 );   48    49 /// `LoadGlyph` allows for copying a rasterized glyph into graphics memory   50 pub trait LoadGlyph {   51  /// Load the rasterized glyph into GPU memory   52  fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph;   53 }   54    55 enum Msg {   56  ShaderReload, 1,1Top[?12l[?25h[?25l2[?12l[?25h[?25l3[?12l[?25h[?25l4[?12l[?25h[?25l5[?12l[?25h[?25l6[?12l[?25h[?25l7[?12l[?25h[?25l8[?12l[?25h[?25l9[?12l[?25h[?25l10,1[?12l[?25h[?25l1[?12l[?25h[?25l2[?12l[?25h[?25l3[?12l[?25h[?25l4[?12l[?25h[?25l5[?12l[?25h[?25l6[?12l[?25h[?25l7[?12l[?25h[?25l8[?12l[?25h[?25l9[?12l[?25h[?25l20[?12l[?25h[?25l1[?12l[?25h[?25l2,0-1[?12l[?25h[?25l3,1 [?12l[?25h[?25l4[?12l[?25h[?25l5[?12l[?25h[?25l6[?12l[?25h[?25l7[?12l[?25h[?25l8[?12l[?25h[?25l9[?12l[?25h[?25l30,0-1[?12l[?25h[?25l1,1 [?12l[?25h[?25l2[?12l[?25h[?25l3[?12l[?25h[?25l4,0-1[?12l[?25h[?25l5,1 [?12l[?25h[?25l6,0-1[?12l[?25h[?25l7,1 [?12l[?25h[?25l8[?12l[?25h[?25l9[?12l[?25h[?25l40,0-1[?12l[?25h[?25l1,1 [?12l[?25h[?25l2[?12l[?25h[?25l3[?12l[?25h[?25l()4[?12l[?25h[?25l( );5[?12l[?25h[?25l6[?12l[?25h[?25l()7[?12l[?25h[?25l( );8,0-1[?12l[?25h[?25l9,1 [?12l[?25h[?25l50[?12l[?25h[?25l1[?12l[?25h[?25l2[?12l[?25h[?25l{}3[?12l[?25h[?25l{ } 4,0-1[?12l[?25h[?25l5,1 [?12l[?25h[?25l6[?12l[?25h[?25l {  57 } 57,10%[?12l[?25h[?25l { }  58  58,0-10%[?12l[?25h[?25l  59 #[derive(Debug)] 59,10%[?12l[?25h[?25l  60 pub enum Error { 60,10%[?12l[?25h[?25l  61  ShaderCreation(ShaderCreationError), 61,10%[?12l[?25h[?25l {  62 } 62,10%[?12l[?25h[?25l { }  63  63,0-10%[?12l[?25h[?25l  64 impl ::std::error::Error for Error { 64,10%[?12l[?25h[?25l  65  fn cause(&self) -> Option<&::std::error::Error> { 65,10%[?12l[?25h[?25l  66 match *self { 66,10%[?12l[?25h[?25l  67 Error::ShaderCreation(ref err) => Some(err), 67,10%[?12l[?25h[?25l  68 } 68,10%[?12l[?25h[?25l  69  } 69,11%[?12l[?25h[?25l  70  70,0-11%[?12l[?25h[?25l  71  fn description(&self) -> &str { 71,11%[?12l[?25h[?25l  72 match *self { 72,11%[?12l[?25h[?25l  73 Error::ShaderCreation(ref err) => err.description(), 73,11%[?12l[?25h[?25l  74 } 74,11%[?12l[?25h[?25l  75  } 75,11%[?12l[?25h[?25l { 76 } 76,11%[?12l[?25h[?25l { }  77  77,0-11%[?12l[?25h[?25l  78 impl ::std::fmt::Display for Error { 78,11%[?12l[?25h[?25l  79  fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 79,11%[?12l[?25h[?25l  80 match *self { 80,11%[?12l[?25h[?25l  81 Error::ShaderCreation(ref err) => { 81,11%[?12l[?25h[?25l  82 write!(f, "There was an error initializing the shaders: {}", err) 82,12%[?12l[?25h[?25l  83 } 83,12%[?12l[?25h[?25l  84 } 84,12%[?12l[?25h[?25l  85  } 85,12%[?12l[?25h[?25l { 86 } 86,12%[?12l[?25h[?25l { }  87  87,0-12%[?12l[?25h[?25l  88 impl From<ShaderCreationError> for Error { 88,12%[?12l[?25h[?25l  89  fn from(val: ShaderCreationError) -> Error { 89,12%[?12l[?25h[?25l  90 Error::ShaderCreation(val) 90,12%[?12l[?25h[?25l  91  } 91,12%[?12l[?25h[?25l { 92 } 92,12%[?12l[?25h[?25l { }  93  93,0-12%[?12l[?25h[?25l  94  94,0-12%[?12l[?25h[?25l  95 /// Text drawing program 95,13%[?12l[?25h[?25l  96 /// 96,13%[?12l[?25h[?25l  97 /// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a". 97,13%[?12l[?25h[?25l  98 #[derive(Debug)] 98,13%[?12l[?25h[?25l  99 pub struct ShaderProgram { 99,13%[?12l[?25h[?25l  100  // Program id 100,13%[?12l[?25h[?25l  101  id: GLuint, 101,13%[?12l[?25h[?25l  102  102,0-13%[?12l[?25h[?25l  103  /// projection matrix uniform 103,13%[?12l[?25h[?25l  104  u_projection: GLint, 104,13%[?12l[?25h[?25l  105  105,0-13%[?12l[?25h[?25l  106  /// Terminal dimensions (pixels) 106,13%[?12l[?25h[?25l  107  u_term_dim: GLint, 107,13%[?12l[?25h[?25l  108  108,0-14%[?12l[?25h[?25l  109  /// Cell dimensions (pixels) 109,14%[?12l[?25h[?25l  110  u_cell_dim: GLint, 110,14%[?12l[?25h[?25l  111  111,0-14%[?12l[?25h[?25l  112  /// Visual bell 112,14%[?12l[?25h[?25l  113  u_visual_bell: GLint, 113,14%[?12l[?25h[?25l  114  114,0-14%[?12l[?25h[?25l  115  /// Background pass flag 115,14%[?12l[?25h[?25l  116  /// 116,14%[?12l[?25h[?25l  117  /// Rendering is split into two passes; 1 for backgrounds, and one for text 117,14%[?12l[?25h[?25l  118  u_background: GLint, 118,14%[?12l[?25h[?25l  119  119,0-14%[?12l[?25h[?25l  120  padding_x: f32, 120,14%[?12l[?25h[?25l  121  padding_y: f32, 121,15%[?12l[?25h[?25l { 122 } 122,15%[?12l[?25h[?25l { }  123  123,0-15%[?12l[?25h[?25l  124  124,0-15%[?12l[?25h[?25l  125 #[derive(Debug, Clone)] 125,15%[?12l[?25h[?25l  126 pub struct Glyph { 126,15%[?12l[?25h[?25l  127  tex_id: GLuint, 127,15%[?12l[?25h[?25l  128  top: f32, 128,15%[?12l[?25h[?25l  129  left: f32, 129,15%[?12l[?25h[?25l  130  width: f32, 130,15%[?12l[?25h[?25l  131  height: f32, 131,15%[?12l[?25h[?25l  132  uv_bot: f32, 132,15%[?12l[?25h[?25l  133  uv_left: f32, 133,15%[?12l[?25h[?25l  134  uv_width: f32, 134,16%[?12l[?25h[?25l  135  uv_height: f32, 135,16%[?12l[?25h[?25l { 136 } 136,16%[?12l[?25h[?25l { }  137  137,0-16%[?12l[?25h[?25l  138 /// Naïve glyph cache 138,16%[?12l[?25h[?25l  139 /// 139,16%[?12l[?25h[?25l  140 /// Currently only keyed by `char`, and thus not possible to hold different 140,16%[?12l[?25h[?25l  141 /// representations of the same code point. 141,16%[?12l[?25h[?25l  142 pub struct GlyphCache { 142,16%[?12l[?25h[?25l  143  /// Cache of buffered glyphs 143,16%[?12l[?25h[?25l  144  cache: HashMap<GlyphKey, Glyph, BuildHasherDefault<FnvHasher>>, 144,16%[?12l[?25h[?25l  145  145,0-16%[?12l[?25h[?25l  146  /// Rasterizer for loading new glyphs 146,16%[?12l[?25h[?25l  147  rasterizer: Rasterizer, 147,17%[?12l[?25h[?25l  148  148,0-17%[?12l[?25h[?25l  149  /// regular font 149,17%[?12l[?25h[?25l  150  font_key: FontKey, 150,17%[?12l[?25h[?25l  151  151,0-17%[?12l[?25h[?25l  152  /// italic font 152,17%[?12l[?25h[?25l  153  italic_key: FontKey, 153,17%[?12l[?25h[?25l  154  154,0-17%[?12l[?25h[?25l  155  /// bold font 155,17%[?12l[?25h[?25l  156  bold_key: FontKey, 156,17%[?12l[?25h[?25l  157  157,0-17%[?12l[?25h[?25l  158  /// font size 158,17%[?12l[?25h[?25l  159  font_size: font::Size, 159,17%[?12l[?25h[?25l  160  160,0-18%[?12l[?25h[?25l  161  /// glyph offset 161,18%[?12l[?25h[?25l  162  glyph_offset: Delta, 162,18%[?12l[?25h[?25l  163  163,0-18%[?12l[?25h[?25l  164  metrics: ::font::Metrics, 164,18%[?12l[?25h[?25l { 165 } 165,18%[?12l[?25h[?25l { }  166  166,0-18%[?12l[?25h[?25l  167 impl GlyphCache { 167,18%[?12l[?25h[?25l  168  pub fn new<L>( 168,18%[?12l[?25h[?25l  169 mut rasterizer: Rasterizer, 169,18%[?12l[?25h[?25l  170 config: &Config, 170,18%[?12l[?25h[?25l  171 loader: &mut L 171,18%[?12l[?25h[?25l  172  ) -> Result<GlyphCache, font::Error> 172,18%[?12l[?25h[?25l  173 where L: LoadGlyph 173,19%[?12l[?25h[?25l  174  { 174,19%[?12l[?25h[?25l  175 let font = config.font(); 175,19%[?12l[?25h[?25l  176 let size = font.size(); 176,19%[?12l[?25h[?25l  177 let glyph_offset = *font.glyph_offset(); 177,19%[?12l[?25h[?25l  178  178,0-19%[?12l[?25h[?25l  179 fn make_desc( 179,19%[?12l[?25h[?25l  180 desc: &config::FontDescription, 180,19%[?12l[?25h[?25l  181 slant: font::Slant, 181,19%[?12l[?25h[?25l  182 weight: font::Weight, 182,19%[?12l[?25h[?25l  183 ) -> FontDesc 183,19%[?12l[?25h[?25l  184 { 184,19%[?12l[?25h[?25l  185 let style = if let Some(ref spec) = desc.style { 185,19%[?12l[?25h[?25l  186 font::Style::Specific(spec.to_owned()) 186,110%[?12l[?25h[?25l  187 } else { 187,110%[?12l[?25h[?25l  188 font::Style::Description {slant:slant, weight:weight} 188,110%[?12l[?25h[?25l  189 }; 189,110%[?12l[?25h[?25l  190 FontDesc::new(&desc.family[..], style) 190,110%[?12l[?25h[?25l  191 } 191,110%[?12l[?25h[?25l  192  192,0-110%[?12l[?25h[?25l  193 // Load regular font 193,110%[?12l[?25h[?25l  194 let regular_desc = make_desc(&font.normal, font::Slant::Normal, font::Weight::Normal);  194,110%[?12l[?25h[?25l  195  195,0-110%[?12l[?25h[?25l  196 let regular = rasterizer 196,110%[?12l[?25h[?25l  197 .load_font(®ular_desc, size)?; 197,110%[?12l[?25h[?25l  198  198,0-110%[?12l[?25h[?25l  199 // helper to load a description if it is not the regular_desc 199,111%[?12l[?25h[?25l  200 let load_or_regular = |desc:FontDesc, rasterizer: &mut Rasterizer| { 200,111%[?12l[?25h[?25l  201 if desc == regular_desc { 201,111%[?12l[?25h[?25l  202 regular 202,111%[?12l[?25h[?25l  203 } else { 203,111%[?12l[?25h[?25l  204 rasterizer.load_font(&desc, size).unwrap_or_else(|_| regular) 204,111%[?12l[?25h[?25l  205 } 205,111%[?12l[?25h[?25l  206 }; 206,111%[?12l[?25h[?25l  207  207,0-111%[?12l[?25h[?25l  208 // Load bold font 208,111%[?12l[?25h[?25l  209 let bold_desc = make_desc(&font.bold, font::Slant::Normal, font::Weight::Bold); 209,111%[?12l[?25h[?25l  210  210,0-111%[?12l[?25h[?25l  211 let bold = load_or_regular(bold_desc, &mut rasterizer); 211,111%[?12l[?25h[?25l  212  212,0-112%[?12l[?25h[?25l  213 // Load italic font 213,112%[?12l[?25h[?25l  214 let italic_desc = make_desc(&font.italic, font::Slant::Italic, font::Weight::Normal); 214,112%[?12l[?25h[?25l  215  215,0-112%[?12l[?25h[?25l  216 let italic = load_or_regular(italic_desc, &mut rasterizer); 216,112%[?12l[?25h[?25l  217  217,0-112%[?12l[?25h[?25l  218 // Need to load at least one glyph for the face before calling metrics. 218,112%[?12l[?25h[?25l  219 // The glyph requested here ('m' at the time of writing) has no special 219,112%[?12l[?25h[?25l  220 // meaning. 220,112%[?12l[?25h[?25l  221 rasterizer.get_glyph(&GlyphKey { font_key: regular, c: 'm', size: font.size() })?; 221,112%[?12l[?25h[?25l  222 let metrics = rasterizer.metrics(regular)?; 222,112%[?12l[?25h[?25l  223  223,0-112%[?12l[?25h[?25l  224 let mut cache = GlyphCache { 224,112%[?12l[?25h[?25l  225 cache: HashMap::default(), 225,113%[?12l[?25h[?25l  226 rasterizer: rasterizer, 226,113%[?12l[?25h[?25l  227 font_size: font.size(), 227,113%[?12l[?25h[?25l  228 font_key: regular, 228,113%[?12l[?25h[?25l  229 bold_key: bold, 229,113%[?12l[?25h[?25l  230 italic_key: italic, 230,113%[?12l[?25h[?25l  231 glyph_offset: glyph_offset, 231,113%[?12l[?25h[?25l  232 metrics: metrics 232,113%[?12l[?25h[?25l  233 }; 233,113%[?12l[?25h[?25l  234  234,0-113%[?12l[?25h[?25l  235 macro_rules! load_glyphs_for_font { 235,113%[?12l[?25h[?25l  236 ($font:expr) => { 236,113%[?12l[?25h[?25l  237 for i in RangeInclusive::new(32u8, 128u8) { 237,113%[?12l[?25h[?25l  238 cache.get(&GlyphKey { 238,114%[?12l[?25h[?25l  239 font_key: $font, 239,114%[?12l[?25h[?25l  240 c: i as char, 240,114%[?12l[?25h[?25l  241 size: font.size() 241,114%[?12l[?25h[?25l  242 }, loader); 242,114%[?12l[?25h[?25l  243 } 243,114%[?12l[?25h[?25l  244 } 244,114%[?12l[?25h[?25l  245 } 245,114%[?12l[?25h[?25l  246  246,0-114%[?12l[?25h[?25l  247 load_glyphs_for_font!(regular); 247,114%[?12l[?25h[?25l  248 load_glyphs_for_font!(bold); 248,114%[?12l[?25h[?25l  249 load_glyphs_for_font!(italic); 249,114%[?12l[?25h[?25l  250  250,0-114%[?12l[?25h[?25l  251 Ok(cache) 251,115%[?12l[?25h[?25l  252  } 252,115%[?12l[?25h[?25l  253  253,0-115%[?12l[?25h[?25l  254  pub fn font_metrics(&self) -> font::Metrics { 254,115%[?12l[?25h[?25l  255 self.rasterizer 255,115%[?12l[?25h[?25l  256 .metrics(self.font_key) 256,115%[?12l[?25h[?25l  257 .expect("metrics load since font is loaded at glyph cache creation") 257,115%[?12l[?25h[?25l  258  } 258,115%[?12l[?25h[?25l  259  259,0-115%[?12l[?25h[?25l  260  pub fn get<'a, L>(&'a mut self, glyph_key: &GlyphKey, loader: &mut L) -> &'a Glyph 260,115%[?12l[?25h[?25l  261 where L: LoadGlyph 261,115%[?12l[?25h[?25l  262  { 262,115%[?12l[?25h[?25l  263 let glyph_offset = self.glyph_offset; 263,115%[?12l[?25h[?25l  264 let rasterizer = &mut self.rasterizer; 264,116%[?12l[?25h[?25l  265 let metrics = &self.metrics; 265,116%[?12l[?25h[?25l  266 self.cache 266,116%[?12l[?25h[?25l  267 .entry(*glyph_key) 267,116%[?12l[?25h[?25l  268 .or_insert_with(|| { 268,116%[?12l[?25h[?25l  269 let mut rasterized = rasterizer.get_glyph(&glyph_key) 269,116%[?12l[?25h[?25l  270 .unwrap_or_else(|_| Default::default()); 270,116%[?12l[?25h[?25l  271  271,0-116%[?12l[?25h[?25l  272 rasterized.left += glyph_offset.x as i32; 272,116%[?12l[?25h[?25l  273 rasterized.top += glyph_offset.y as i32; 273,116%[?12l[?25h[?25l  274 rasterized.top -= metrics.descent as i32; 274,116%[?12l[?25h[?25l  275  275,0-116%[?12l[?25h[?25l  276 loader.load_glyph(&rasterized) 276,116%[?12l[?25h[?25l  277 }) 277,117%[?12l[?25h[?25l  278  } 278,117%[?12l[?25h[?25l  279 } 279,117%[?12l[?25h[?25l  280  280,0-117%[?12l[?25h[?25l  281 #[derive(Debug)] 281,117%[?12l[?25h[?25l  282 #[repr(C)] 282,117%[?12l[?25h[?25l  283 struct InstanceData { 283,117%[?12l[?25h[?25l  284  // coords 284,117%[?12l[?25h[?25l  285  col: f32, 285,117%[?12l[?25h[?25l  286  row: f32, 286,117%[?12l[?25h[?25l  287  // glyph offset 287,117%[?12l[?25h[?25l  288  left: f32, 288,117%[?12l[?25h[?25l  289  top: f32, 289,117%[?12l[?25h[?25l  290  // glyph scale 290,118%[?12l[?25h[?25l  291  width: f32, 291,118%[?12l[?25h[?25l  292  height: f32, 292,118%[?12l[?25h[?25l  293  // uv offset 293,118%[?12l[?25h[?25l  294  uv_left: f32, 294,118%[?12l[?25h[?25l  295  uv_bot: f32, 295,118%[?12l[?25h[?25l  296  // uv scale 296,118%[?12l[?25h[?25l  297  uv_width: f32, 297,118%[?12l[?25h[?25l  298  uv_height: f32, 298,118%[?12l[?25h[?25l  299  // color 299,118%[?12l[?25h[?25l  300  r: f32, 300,118%[?12l[?25h[?25l  301  g: f32, 301,118%[?12l[?25h[?25l  302  b: f32, 302,118%[?12l[?25h[?25l  303  // background color 303,119%[?12l[?25h[?25l  304  bg_r: f32, 304,119%[?12l[?25h[?25l  305  bg_g: f32, 305,119%[?12l[?25h[?25l  306  bg_b: f32, 306,119%[?12l[?25h[?25l { 307 } 307,119%[?12l[?25h[?25l { }  308  308,0-119%[?12l[?25h[?25l  309 #[derive(Debug)] 309,119%[?12l[?25h[?25l  310 pub struct QuadRenderer { 310,119%[?12l[?25h[?25l  311  program: ShaderProgram, 311,119%[?12l[?25h[?25l  312  vao: GLuint, 312,119%[?12l[?25h[?25l  313  vbo: GLuint, 313,119%[?12l[?25h[?25l  314  ebo: GLuint, 314,119%[?12l[?25h[?25l  315  vbo_instance: GLuint, 315,119%[?12l[?25h[?25l  316  atlas: Vec<Atlas>, 316,120%[?12l[?25h[?25l  317  active_tex: GLuint, 317,120%[?12l[?25h[?25l  318  batch: Batch, 318,120%[?12l[?25h[?25l  319  rx: mpsc::Receiver<Msg>, 319,120%[?12l[?25h[?25l { 320 } 320,120%[?12l[?25h[?25l { }  321  321,0-120%[?12l[?25h[?25l  322 #[derive(Debug)] 322,120%[?12l[?25h[?25l  323 pub struct RenderApi<'a> { 323,120%[?12l[?25h[?25l  324  active_tex: &'a mut GLuint, 324,120%[?12l[?25h[?25l  325  batch: &'a mut Batch, 325,120%[?12l[?25h[?25l  326  atlas: &'a mut Vec<Atlas>, 326,120%[?12l[?25h[?25l  327  program: &'a mut ShaderProgram, 327,120%[?12l[?25h[?25l  328  config: &'a Config, 328,120%[?12l[?25h[?25l  329  visual_bell_intensity: f32 329,121%[?12l[?25h[?25l { 330 } 330,121%[?12l[?25h[?25l { }  331  331,0-121%[?12l[?25h[?25l  332 #[derive(Debug)] 332,121%[?12l[?25h[?25l  333 pub struct LoaderApi<'a> { 333,121%[?12l[?25h[?25l  334  active_tex: &'a mut GLuint, 334,121%[?12l[?25h[?25l  335  atlas: &'a mut Vec<Atlas>, 335,121%[?12l[?25h[?25l {  336 } 336,121%[?12l[?25h[?25l { }  337  337,0-121%[?12l[?25h[?25l  338 #[derive(Debug)] 338,121%[?12l[?25h[?25l  339 pub struct PackedVertex { 339,121%[?12l[?25h[?25l  340  x: f32, 340,121%[?12l[?25h[?25l  341  y: f32, 341,121%[?12l[?25h[?25l {  342 } 342,122%[?12l[?25h[?25l { }  343  343,0-122%[?12l[?25h[?25l  344 #[derive(Debug)] 344,122%[?12l[?25h[?25l  345 pub struct Batch { 345,122%[?12l[?25h[?25l  346  tex: GLuint, 346,122%[?12l[?25h[?25l  347  instances: Vec<InstanceData>, 347,122%[?12l[?25h[?25l 348 }   349    350 impl Batch {   351  #[inline]   352  pub fn new() -> Batch {   353 Batch {   354 tex: 0,   355 instances: Vec::with_capacity(BATCH_MAX),   356 }   357  }   358    359  pub fn add_item(   360 &mut self,   361 cell: &RenderableCell,   362 glyph: &Glyph,   363  ) {   364 if self.is_empty() {   365 self.tex = glyph.tex_id;   366 }   367    368 self.instances.push(InstanceData {   369 col: cell.column.0 as f32,   370 row: cell.line.0 as f32,   371    372 top: glyph.top,   373 left: glyph.left,   374 width: glyph.width,   375 height: glyph.height, 375,1324%[?12l[?25h[?25l 376    377 uv_bot: glyph.uv_bot,   378 uv_left: glyph.uv_left,   379 uv_width: glyph.uv_width,   380 uv_height: glyph.uv_height,   381    382 r: cell.fg.r as f32,   383 g: cell.fg.g as f32,   384 b: cell.fg.b as f32,   385    386 bg_r: cell.bg.r as f32,   387 bg_g: cell.bg.g as f32,   388 bg_b: cell.bg.b as f32,   389 });   390  }   391    392  #[inline]   393  pub fn full(&self) -> bool {   394 self.capacity() == self.len()   395  }   396    397  #[inline]   398  pub fn len(&self) -> usize {   399 self.instances.len()   400  }   401    402  #[inline]   403  pub fn capacity(&self) -> usize { 403,526%[?12l[?25h[?25l 404 BATCH_MAX   405  }   406    407  #[inline]   408  pub fn is_empty(&self) -> bool {   409 self.len() == 0   410  }   411    412  #[inline]   413  pub fn size(&self) -> usize {   414 self.len() * size_of::<InstanceData>()   415  }   416    417  pub fn clear(&mut self) {   418 self.tex = 0;   419 self.instances.clear();   420  }   421 }   422    423 /// Maximum items to be drawn in a batch.   424 const BATCH_MAX: usize = 65_536;   425 const ATLAS_SIZE: i32 = 1024;   426    427 impl QuadRenderer {   428  // TODO should probably hand this a transform instead of width/height   429  pub fn new(config: &Config, size: Size<Pixels<u32>>) -> Result<QuadRenderer, Error> {   430 let program = ShaderProgram::new(config, size)?;   431  431,0-128%[?12l[?25h[?25l 432 let mut vao: GLuint = 0;   433 let mut vbo: GLuint = 0;   434 let mut ebo: GLuint = 0;   435    436 let mut vbo_instance: GLuint = 0;   437    438 unsafe {   439 gl::Enable(gl::BLEND);   440 gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);   441 gl::Enable(gl::MULTISAMPLE);   442    443 gl::GenVertexArrays(1, &mut vao);   444 gl::GenBuffers(1, &mut vbo);   445 gl::GenBuffers(1, &mut ebo);   446 gl::GenBuffers(1, &mut vbo_instance);   447 gl::BindVertexArray(vao);   448    449 // ----------------------------   450 // setup vertex position buffer   451 // ----------------------------   452 // Top right, Bottom right, Bottom left, Top left   453 let vertices = [   454 PackedVertex { x: 1.0, y: 1.0 },   455 PackedVertex { x: 1.0, y: 0.0 },   456 PackedVertex { x: 0.0, y: 0.0 },   457 PackedVertex { x: 0.0, y: 1.0 },   458 ];   459  459,0-131%[?12l[?25h[?25l 460 gl::BindBuffer(gl::ARRAY_BUFFER, vbo);   461    462 gl::VertexAttribPointer(0, 2,   463 gl::FLOAT, gl::FALSE,   464 size_of::<PackedVertex>() as i32,   465 ptr::null());   466 gl::EnableVertexAttribArray(0);   467    468 gl::BufferData(gl::ARRAY_BUFFER,   469 (size_of::<PackedVertex>() * vertices.len()) as GLsizeiptr,   470 vertices.as_ptr() as *const _,   471 gl::STATIC_DRAW);   472    473 // ---------------------   474 // Set up element buffer   475 // ---------------------   476 let indices: [u32; 6] = [0, 1, 3,   477 1, 2, 3];   478    479 gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);   480 gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,   481 (6 * size_of::<u32>()) as isize,   482 indices.as_ptr() as *const _,   483 gl::STATIC_DRAW);   484    485 // ----------------------------   486 // Setup vertex instance buffer   487 // ---------------------------- 487,1333%[?12l[?25h[?25l 488 gl::BindBuffer(gl::ARRAY_BUFFER, vbo_instance);   489 gl::BufferData(gl::ARRAY_BUFFER,   490 (BATCH_MAX * size_of::<InstanceData>()) as isize,   491 ptr::null(), gl::STREAM_DRAW);   492 // coords   493 gl::VertexAttribPointer(1, 2,   494 gl::FLOAT, gl::FALSE,   495 size_of::<InstanceData>() as i32,   496 ptr::null());   497 gl::EnableVertexAttribArray(1);   498 gl::VertexAttribDivisor(1, 1);   499 // glyphoffset   500 gl::VertexAttribPointer(2, 4,   501 gl::FLOAT, gl::FALSE,   502 size_of::<InstanceData>() as i32,   503 (2 * size_of::<f32>()) as *const _);   504 gl::EnableVertexAttribArray(2);   505 gl::VertexAttribDivisor(2, 1);   506 // uv   507 gl::VertexAttribPointer(3, 4,   508 gl::FLOAT, gl::FALSE,   509 size_of::<InstanceData>() as i32,   510 (6 * size_of::<f32>()) as *const _);   511 gl::EnableVertexAttribArray(3);   512 gl::VertexAttribDivisor(3, 1);   513 // color   514 gl::VertexAttribPointer(4, 3,   515 gl::FLOAT, gl::FALSE, 515,3735%[?12l[?25h[?25l 516 size_of::<InstanceData>() as i32,   517 (10 * size_of::<f32>()) as *const _);   518 gl::EnableVertexAttribArray(4);   519 gl::VertexAttribDivisor(4, 1);   520 // color   521 gl::VertexAttribPointer(5, 3,   522 gl::FLOAT, gl::FALSE,   523 size_of::<InstanceData>() as i32,   524 (13 * size_of::<f32>()) as *const _);   525 gl::EnableVertexAttribArray(5);   526 gl::VertexAttribDivisor(5, 1);   527    528 gl::BindVertexArray(0);   529 gl::BindBuffer(gl::ARRAY_BUFFER, 0);   530 }   531    532 let (msg_tx, msg_rx) = mpsc::channel();   533    534 if cfg!(feature = "live-shader-reload") {   535 ::std::thread::spawn(move || {   536 let (tx, rx) = ::std::sync::mpsc::channel();   537 let mut watcher = Watcher::new(tx).expect("create file watcher");   538 watcher.watch(TEXT_SHADER_F_PATH).expect("watch fragment shader");   539 watcher.watch(TEXT_SHADER_V_PATH).expect("watch vertex shader");   540    541 loop {   542 let event = rx.recv().expect("watcher event");   543 let ::notify::Event { path, op } = event; 543,2137%[?12l[?25h[?25l 544    545 if let Ok(op) = op {   546 if op.contains(op::RENAME) {   547 continue;   548 }   549    550 if op.contains(op::IGNORED) {   551 if let Some(path) = path.as_ref() {   552 if let Err(err) = watcher.watch(path) {   553 warn!("failed to establish watch on {:?}: {:?}", path, err);    554 }   555 }   556    557 msg_tx.send(Msg::ShaderReload)   558 .expect("msg send ok");   559 }   560 }   561 }   562 });   563 }   564    565 let mut renderer = QuadRenderer {   566 program: program,   567 vao: vao,   568 vbo: vbo,   569 ebo: ebo,   570 vbo_instance: vbo_instance,   571 atlas: Vec::new(), 571,1339%[?12l[?25h[?25l 572 active_tex: 0,   573 batch: Batch::new(),   574 rx: msg_rx,   575 };   576    577 let atlas = Atlas::new(ATLAS_SIZE);   578 renderer.atlas.push(atlas);   579    580 Ok(renderer)   581  }   582    583  pub fn with_api<F, T>(   584 &mut self,   585 config: &Config,   586 props: &term::SizeInfo,   587 visual_bell_intensity: f64,   588 func: F   589  ) -> T   590 where F: FnOnce(RenderApi) -> T   591  {   592 while let Ok(msg) = self.rx.try_recv() {   593 match msg {   594 Msg::ShaderReload => {   595 self.reload_shaders(&config, Size {   596 width: Pixels(props.width as u32),   597 height: Pixels(props.height as u32)   598 });   599 } 599,1741%[?12l[?25h[?25l{ }  600 }   601 }   602    603 unsafe {   604 self.program.activate();   605 self.program.set_term_uniforms(props);   606 self.program.set_visual_bell(visual_bell_intensity as _);   607    608 gl::BindVertexArray(self.vao);   609 gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo);   610 gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo_instance);   611 gl::ActiveTexture(gl::TEXTURE0);   612 }   613    614 let res = func(RenderApi {   615 active_tex: &mut self.active_tex,   616 batch: &mut self.batch,   617 atlas: &mut self.atlas,   618 program: &mut self.program,   619 visual_bell_intensity: visual_bell_intensity as _,   620 config: config,   621 });   622    623 unsafe {   624 gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0);   625 gl::BindBuffer(gl::ARRAY_BUFFER, 0);   626 gl::BindVertexArray(0);   627  627,0-143%[?12l[?25h[?25l 628 self.program.deactivate();   629 }   630    631 res   632  }   633    634  pub fn with_loader<F, T>(&mut self, func: F) -> T   635 where F: FnOnce(LoaderApi) -> T   636  {   637 unsafe {   638 gl::ActiveTexture(gl::TEXTURE0);   639 }   640    641 func(LoaderApi {   642 active_tex: &mut self.active_tex,   643 atlas: &mut self.atlas,   644 })   645  }   646    647  pub fn reload_shaders(&mut self, config: &Config, size: Size<Pixels<u32>>) {   648 info!("Reloading shaders");   649 let program = match ShaderProgram::new(config, size) {   650 Ok(program) => program,   651 Err(err) => {   652 match err {   653 ShaderCreationError::Io(err) => {   654 error!("Error reading shader file: {}", err);   655 }, 655,2146%[?12l[?25h[?25l 572 active_tex: 0,   573 batch: Batch::new(),   574 rx: msg_rx,   575 };   576    577 let atlas = Atlas::new(ATLAS_SIZE);   578 renderer.atlas.push(atlas);   579    580 Ok(renderer)   581  }   582    583  pub fn with_api<F, T>(   584 &mut self,   585 config: &Config,   586 props: &term::SizeInfo,   587 visual_bell_intensity: f64,   588 func: F   589  ) -> T   590 where F: FnOnce(RenderApi) -> T   591  {   592 while let Ok(msg) = self.rx.try_recv() {   593 match msg {   594 Msg::ShaderReload => {   595 self.reload_shaders(&config, Size {   596 width: Pixels(props.width as u32),   597 height: Pixels(props.height as u32)   598 });   599 } 627,0-143%[?12l[?25h[?25l 544    545 if let Ok(op) = op {   546 if op.contains(op::RENAME) {   547 continue;   548 }   549    550 if op.contains(op::IGNORED) {   551 if let Some(path) = path.as_ref() {   552 if let Err(err) = watcher.watch(path) {   553 warn!("failed to establish watch on {:?}: {:?}", path, err);    554 }   555 }   556    557 msg_tx.send(Msg::ShaderReload)   558 .expect("msg send ok");   559 }   560 }   561 }   562 });   563 }   564    565 let mut renderer = QuadRenderer {   566 program: program,   567 vao: vao,   568 vbo: vbo,   569 ebo: ebo,   570 vbo_instance: vbo_instance,   571 atlas: Vec::new(), {}599,1741%[?12l[?25h[?25l 516 size_of::<InstanceData>() as i32,   517 (10 * size_of::<f32>()) as *const _);   518 gl::EnableVertexAttribArray(4);   519 gl::VertexAttribDivisor(4, 1);   520 // color   521 gl::VertexAttribPointer(5, 3,   522 gl::FLOAT, gl::FALSE,   523 size_of::<InstanceData>() as i32,   524 (13 * size_of::<f32>()) as *const _);   525 gl::EnableVertexAttribArray(5);   526 gl::VertexAttribDivisor(5, 1);   527    528 gl::BindVertexArray(0);   529 gl::BindBuffer(gl::ARRAY_BUFFER, 0);   530 }   531    532 let (msg_tx, msg_rx) = mpsc::channel();   533    534 if cfg!(feature = "live-shader-reload") {   535 ::std::thread::spawn(move || {   536 let (tx, rx) = ::std::sync::mpsc::channel();   537 let mut watcher = Watcher::new(tx).expect("create file watcher");   538 watcher.watch(TEXT_SHADER_F_PATH).expect("watch fragment shader");   539 watcher.watch(TEXT_SHADER_V_PATH).expect("watch vertex shader");   540    541 loop {   542 let event = rx.recv().expect("watcher event");   543 let ::notify::Event { path, op } = event; 571,1339%[?12l[?25h[?25l 488 gl::BindBuffer(gl::ARRAY_BUFFER, vbo_instance);   489 gl::BufferData(gl::ARRAY_BUFFER,   490 (BATCH_MAX * size_of::<InstanceData>()) as isize,   491 ptr::null(), gl::STREAM_DRAW);   492 // coords   493 gl::VertexAttribPointer(1, 2,   494 gl::FLOAT, gl::FALSE,   495 size_of::<InstanceData>() as i32,   496 ptr::null());   497 gl::EnableVertexAttribArray(1);   498 gl::VertexAttribDivisor(1, 1);   499 // glyphoffset   500 gl::VertexAttribPointer(2, 4,   501 gl::FLOAT, gl::FALSE,   502 size_of::<InstanceData>() as i32,   503 (2 * size_of::<f32>()) as *const _);   504 gl::EnableVertexAttribArray(2);   505 gl::VertexAttribDivisor(2, 1);   506 // uv   507 gl::VertexAttribPointer(3, 4,   508 gl::FLOAT, gl::FALSE,   509 size_of::<InstanceData>() as i32,   510 (6 * size_of::<f32>()) as *const _);   511 gl::EnableVertexAttribArray(3);   512 gl::VertexAttribDivisor(3, 1);   513 // color   514 gl::VertexAttribPointer(4, 3,   515 gl::FLOAT, gl::FALSE, 543,2137%[?12l[?25h[?25l 460 gl::BindBuffer(gl::ARRAY_BUFFER, vbo);   461    462 gl::VertexAttribPointer(0, 2,   463 gl::FLOAT, gl::FALSE,   464 size_of::<PackedVertex>() as i32,   465 ptr::null());   466 gl::EnableVertexAttribArray(0);   467    468 gl::BufferData(gl::ARRAY_BUFFER,   469 (size_of::<PackedVertex>() * vertices.len()) as GLsizeiptr,   470 vertices.as_ptr() as *const _,   471 gl::STATIC_DRAW);   472    473 // ---------------------   474 // Set up element buffer   475 // ---------------------   476 let indices: [u32; 6] = [0, 1, 3,   477 1, 2, 3];   478    479 gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);   480 gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,   481 (6 * size_of::<u32>()) as isize,   482 indices.as_ptr() as *const _,   483 gl::STATIC_DRAW);   484    485 // ----------------------------   486 // Setup vertex instance buffer   487 // ---------------------------- 515,3735%[?12l[?25h[?25l 432 let mut vao: GLuint = 0;   433 let mut vbo: GLuint = 0;   434 let mut ebo: GLuint = 0;   435    436 let mut vbo_instance: GLuint = 0;   437    438 unsafe {   439 gl::Enable(gl::BLEND);   440 gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);   441 gl::Enable(gl::MULTISAMPLE);   442    443 gl::GenVertexArrays(1, &mut vao);   444 gl::GenBuffers(1, &mut vbo);   445 gl::GenBuffers(1, &mut ebo);   446 gl::GenBuffers(1, &mut vbo_instance);   447 gl::BindVertexArray(vao);   448    449 // ----------------------------   450 // setup vertex position buffer   451 // ----------------------------   452 // Top right, Bottom right, Bottom left, Top left   453 let vertices = [   454 PackedVertex { x: 1.0, y: 1.0 },   455 PackedVertex { x: 1.0, y: 0.0 },   456 PackedVertex { x: 0.0, y: 0.0 },   457 PackedVertex { x: 0.0, y: 1.0 },   458 ];   459  487,1333%[?12l[?25h[?25l 404 BATCH_MAX   405  }   406    407  #[inline]   408  pub fn is_empty(&self) -> bool {   409 self.len() == 0   410  }   411    412  #[inline]   413  pub fn size(&self) -> usize {   414 self.len() * size_of::<InstanceData>()   415  }   416    417  pub fn clear(&mut self) {   418 self.tex = 0;   419 self.instances.clear();   420  }   421 }   422    423 /// Maximum items to be drawn in a batch.   424 const BATCH_MAX: usize = 65_536;   425 const ATLAS_SIZE: i32 = 1024;   426    427 impl QuadRenderer {   428  // TODO should probably hand this a transform instead of width/height   429  pub fn new(config: &Config, size: Size<Pixels<u32>>) -> Result<QuadRenderer, Error> {   430 let program = ShaderProgram::new(config, size)?;   431  459,0-131%[?12l[?25h[?25l 376    377 uv_bot: glyph.uv_bot,   378 uv_left: glyph.uv_left,   379 uv_width: glyph.uv_width,   380 uv_height: glyph.uv_height,   381    382 r: cell.fg.r as f32,   383 g: cell.fg.g as f32,   384 b: cell.fg.b as f32,   385    386 bg_r: cell.bg.r as f32,   387 bg_g: cell.bg.g as f32,   388 bg_b: cell.bg.b as f32,   389 });   390  }   391    392  #[inline]   393  pub fn full(&self) -> bool {   394 self.capacity() == self.len()   395  }   396    397  #[inline]   398  pub fn len(&self) -> usize {   399 self.instances.len()   400  }   401    402  #[inline]   403  pub fn capacity(&self) -> usize { 431,0-128%[?12l[?25h[?25l 348 }   349    350 impl Batch {   351  #[inline]   352  pub fn new() -> Batch {   353 Batch {   354 tex: 0,   355 instances: Vec::with_capacity(BATCH_MAX),   356 }   357  }   358    359  pub fn add_item(   360 &mut self,   361 cell: &RenderableCell,   362 glyph: &Glyph,   363  ) {   364 if self.is_empty() {   365 self.tex = glyph.tex_id;   366 }   367    368 self.instances.push(InstanceData {   369 col: cell.column.0 as f32,   370 row: cell.line.0 as f32,   371    372 top: glyph.top,   373 left: glyph.left,   374 width: glyph.width,   375 height: glyph.height, 403,526%[?12l[?25h[?25l 320 }   321    322 #[derive(Debug)]   323 pub struct RenderApi<'a> {   324  active_tex: &'a mut GLuint,   325  batch: &'a mut Batch,   326  atlas: &'a mut Vec<Atlas>,   327  program: &'a mut ShaderProgram,   328  config: &'a Config,   329  visual_bell_intensity: f32   330 }   331    332 #[derive(Debug)]   333 pub struct LoaderApi<'a> {   334  active_tex: &'a mut GLuint,   335  atlas: &'a mut Vec<Atlas>,   336 }   337    338 #[derive(Debug)]   339 pub struct PackedVertex {   340  x: f32,   341  y: f32,   342 }   343    344 #[derive(Debug)]   345 pub struct Batch {   346  tex: GLuint,   347  instances: Vec<InstanceData>, 375,1324%[?12l[?25h[?25l 292  height: f32,   293  // uv offset   294  uv_left: f32,   295  uv_bot: f32,   296  // uv scale   297  uv_width: f32,   298  uv_height: f32,   299  // color   300  r: f32,   301  g: f32,   302  b: f32,   303  // background color   304  bg_r: f32,   305  bg_g: f32,   306  bg_b: f32,   307 }   308    309 #[derive(Debug)]   310 pub struct QuadRenderer {   311  program: ShaderProgram,   312  vao: GLuint,   313  vbo: GLuint,   314  ebo: GLuint,   315  vbo_instance: GLuint,   316  atlas: Vec<Atlas>,   317  active_tex: GLuint,   318  batch: Batch,   319  rx: mpsc::Receiver<Msg>, 347,522%[?12l[?25h[?25l 264 let rasterizer = &mut self.rasterizer;   265 let metrics = &self.metrics;   266 self.cache   267 .entry(*glyph_key)   268 .or_insert_with(|| {   269 let mut rasterized = rasterizer.get_glyph(&glyph_key)   270 .unwrap_or_else(|_| Default::default());   271    272 rasterized.left += glyph_offset.x as i32;   273 rasterized.top += glyph_offset.y as i32;   274 rasterized.top -= metrics.descent as i32;   275    276 loader.load_glyph(&rasterized)   277 })   278  }   279 }   280    281 #[derive(Debug)]   282 #[repr(C)]   283 struct InstanceData {   284  // coords   285  col: f32,   286  row: f32,   287  // glyph offset   288  left: f32,   289  top: f32,   290  // glyph scale   291  width: f32, 319,520%[?12l[?25h[?25l 236 ($font:expr) => {   237 for i in RangeInclusive::new(32u8, 128u8) {   238 cache.get(&GlyphKey {   239 font_key: $font,   240 c: i as char,   241 size: font.size()   242 }, loader);   243 }   244 }   245 }   246    247 load_glyphs_for_font!(regular);   248 load_glyphs_for_font!(bold);   249 load_glyphs_for_font!(italic);   250    251 Ok(cache)   252  }   253    254  pub fn font_metrics(&self) -> font::Metrics {   255 self.rasterizer   256 .metrics(self.font_key)   257 .expect("metrics load since font is loaded at glyph cache creation")   258  }   259    260  pub fn get<'a, L>(&'a mut self, glyph_key: &GlyphKey, loader: &mut L) -> &'a Glyph   261 where L: LoadGlyph   262  {   263 let glyph_offset = self.glyph_offset; 291,518%[?12l[?25h[?25l 208 // Load bold font   209 let bold_desc = make_desc(&font.bold, font::Slant::Normal, font::Weight::Bold);   210    211 let bold = load_or_regular(bold_desc, &mut rasterizer);   212    213 // Load italic font   214 let italic_desc = make_desc(&font.italic, font::Slant::Italic, font::Weight::Normal);   215    216 let italic = load_or_regular(italic_desc, &mut rasterizer);   217    218 // Need to load at least one glyph for the face before calling metrics.   219 // The glyph requested here ('m' at the time of writing) has no special   220 // meaning.   221 rasterizer.get_glyph(&GlyphKey { font_key: regular, c: 'm', size: font.size() })?;   222 let metrics = rasterizer.metrics(regular)?;   223    224 let mut cache = GlyphCache {   225 cache: HashMap::default(),   226 rasterizer: rasterizer,   227 font_size: font.size(),   228 font_key: regular,   229 bold_key: bold,   230 italic_key: italic,   231 glyph_offset: glyph_offset,   232 metrics: metrics   233 };   234    235 macro_rules! load_glyphs_for_font { 263,915%[?12l[?25h[?25l 180 desc: &config::FontDescription,   181 slant: font::Slant,   182 weight: font::Weight,   183 ) -> FontDesc   184 {   185 let style = if let Some(ref spec) = desc.style {   186 font::Style::Specific(spec.to_owned())   187 } else {   188 font::Style::Description {slant:slant, weight:weight}   189 };   190 FontDesc::new(&desc.family[..], style)   191 }   192    193 // Load regular font   194 let regular_desc = make_desc(&font.normal, font::Slant::Normal, font::Weight::Normal);    195    196 let regular = rasterizer   197 .load_font(®ular_desc, size)?;   198    199 // helper to load a description if it is not the regular_desc   200 let load_or_regular = |desc:FontDesc, rasterizer: &mut Rasterizer| {   201 if desc == regular_desc {   202 regular   203 } else {   204 rasterizer.load_font(&desc, size).unwrap_or_else(|_| regular)   205 }   206 };   207  235,913%[?12l[?25h[?25l 152  /// italic font   153  italic_key: FontKey,   154    155  /// bold font   156  bold_key: FontKey,   157    158  /// font size   159  font_size: font::Size,   160    161  /// glyph offset   162  glyph_offset: Delta,   163    164  metrics: ::font::Metrics,   165 }   166    167 impl GlyphCache {   168  pub fn new<L>(   169 mut rasterizer: Rasterizer,   170 config: &Config,   171 loader: &mut L   172  ) -> Result<GlyphCache, font::Error>   173 where L: LoadGlyph   174  {   175 let font = config.font();   176 let size = font.size();   177 let glyph_offset = *font.glyph_offset();   178    179 fn make_desc( 207,0-111%[?12l[?25h[?25l 124    125 #[derive(Debug, Clone)]   126 pub struct Glyph {   127  tex_id: GLuint,   128  top: f32,   129  left: f32,   130  width: f32,   131  height: f32,   132  uv_bot: f32,   133  uv_left: f32,   134  uv_width: f32,   135  uv_height: f32,   136 }   137    138 /// Naïve glyph cache   139 ///   140 /// Currently only keyed by `char`, and thus not possible to hold different   141 /// representations of the same code point.   142 pub struct GlyphCache {   143  /// Cache of buffered glyphs   144  cache: HashMap<GlyphKey, Glyph, BuildHasherDefault<FnvHasher>>,   145    146  /// Rasterizer for loading new glyphs   147  rasterizer: Rasterizer,   148    149  /// regular font   150  font_key: FontKey,   151  179,99%[?12l[?25h[?25l 96 ///   97 /// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a".   98 #[derive(Debug)]   99 pub struct ShaderProgram {   100  // Program id   101  id: GLuint,   102    103  /// projection matrix uniform   104  u_projection: GLint,   105    106  /// Terminal dimensions (pixels)   107  u_term_dim: GLint,   108    109  /// Cell dimensions (pixels)   110  u_cell_dim: GLint,   111    112  /// Visual bell   113  u_visual_bell: GLint,   114    115  /// Background pass flag   116  ///   117  /// Rendering is split into two passes; 1 for backgrounds, and one for text   118  u_background: GLint,   119    120  padding_x: f32,   121  padding_y: f32,   122 }   123  151,0-17%[?12l[?25h[?25l:[?12l[?25hq[?25l[?12l[?25h[?25l[?12l[?25h [?25l151,0-17%[?12l[?25h