basic.rs (5687B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use std::sync::Arc; 6 use std::mem; 7 8 use api::{ 9 IdNamespace, FontTemplate, FontKey, FontInstanceKey, FontInstanceOptions, 10 FontInstancePlatformOptions, ColorF, FontInstanceFlags, units::DevicePoint, 11 }; 12 use glutin::ContextBuilder; 13 use glutin::dpi::PhysicalSize; 14 use glutin::event::{Event, WindowEvent}; 15 use glutin::event_loop::{ControlFlow, EventLoop}; 16 use glutin::window::WindowBuilder; 17 use rayon::ThreadPoolBuilder; 18 use wr_glyph_rasterizer::RasterizedGlyph; 19 use wr_glyph_rasterizer::{ 20 SharedFontResources, BaseFontInstance, GlyphRasterizer, FontInstance, GlyphKey, 21 SubpixelDirection, profiler::GlyphRasterizeProfiler, 22 }; 23 24 #[path = "common/boilerplate.rs"] 25 mod boilerplate; 26 27 struct Profiler; 28 29 impl GlyphRasterizeProfiler for Profiler { 30 fn start_time(&mut self) {} 31 fn end_time(&mut self) -> f64 { 32 0. 33 } 34 fn set(&mut self, _value: f64) {} 35 } 36 37 fn load_glyphs() -> Vec<RasterizedGlyph> { 38 let namespace = IdNamespace(0); 39 let mut fonts = SharedFontResources::new(namespace); 40 41 let font_key = FontKey::new(namespace, 0); 42 let raw_font_data = include_bytes!("../../wrench/reftests/text/FreeSans.ttf"); 43 let font_template = FontTemplate::Raw(Arc::new(raw_font_data.to_vec()), 0); 44 let shared_font_key = fonts 45 .font_keys 46 .add_key(&font_key, &font_template) 47 .expect("Failed to add font key"); 48 49 let font_instance_key = FontInstanceKey::new(namespace, 1); 50 fonts.templates.add_font(shared_font_key, font_template); 51 assert!(fonts.templates.has_font(&shared_font_key)); 52 53 // AddFontInstance will only be processed here, not in the resource cache, so it 54 // is safe to take the options rather than clone them. 55 let base = BaseFontInstance::new( 56 font_instance_key, 57 shared_font_key, 58 32., 59 mem::take(&mut Some(FontInstanceOptions::default())), 60 mem::take(&mut Some(FontInstancePlatformOptions::default())), 61 mem::take(&mut Vec::new()), 62 ); 63 let shared_instance = fonts 64 .instance_keys 65 .add_key(base) 66 .expect("Failed to add font instance key"); 67 fonts.instances.add_font_instance(shared_instance); 68 69 let workers = { 70 let worker = ThreadPoolBuilder::new() 71 .thread_name(|idx| format!("WRWorker#{}", idx)) 72 .build(); 73 Arc::new(worker.unwrap()) 74 }; 75 let mut glyph_rasterizer = GlyphRasterizer::new(workers, None, false); 76 77 glyph_rasterizer.add_font( 78 shared_font_key, 79 fonts 80 .templates 81 .get_font(&shared_font_key) 82 .expect("Could not find FontTemplate"), 83 ); 84 85 let mut font = FontInstance::new( 86 fonts 87 .instances 88 .get_font_instance(font_instance_key) 89 .expect("Could not found BaseFontInstance"), 90 ColorF::BLACK.into(), 91 api::FontRenderMode::Alpha, 92 FontInstanceFlags::SUBPIXEL_POSITION | FontInstanceFlags::FONT_SMOOTHING, 93 ); 94 95 glyph_rasterizer.prepare_font(&mut font); 96 97 let glyph_keys = [ 98 glyph_rasterizer 99 .get_glyph_index(shared_font_key, 'A') 100 .expect("Failed to get glyph index"), 101 glyph_rasterizer 102 .get_glyph_index(shared_font_key, 'B') 103 .expect("Failed to get glyph index"), 104 glyph_rasterizer 105 .get_glyph_index(shared_font_key, 'C') 106 .expect("Failed to get glyph index"), 107 ]; 108 109 let glyph_keys = glyph_keys.map(|g| { 110 GlyphKey::new( 111 g, 112 DevicePoint::new(100., 100.), 113 SubpixelDirection::Horizontal, 114 ) 115 }); 116 117 glyph_rasterizer.request_glyphs(font, &glyph_keys, |_| true); 118 119 let mut glyphs = vec![]; 120 glyph_rasterizer.resolve_glyphs( 121 |job, _| { 122 if let Ok(glyph) = job.result { 123 glyphs.push(glyph); 124 } 125 }, 126 &mut Profiler, 127 ); 128 129 glyphs 130 } 131 132 fn main() { 133 let glyphs = load_glyphs(); 134 135 let el = EventLoop::new(); 136 let wb = WindowBuilder::new() 137 .with_title("A fantastic window!") 138 .with_inner_size(PhysicalSize::new(1900. as f64, 1300. as f64)); 139 140 let windowed_context = ContextBuilder::new() 141 .with_gl(glutin::GlRequest::GlThenGles { 142 opengl_version: (3, 2), 143 opengles_version: (3, 0), 144 }) 145 .build_windowed(wb, &el) 146 .unwrap(); 147 148 let windowed_context = unsafe { windowed_context.make_current().unwrap() }; 149 150 let gl = boilerplate::load(windowed_context.context(), glyphs); 151 152 el.run(move |event, _, control_flow| { 153 *control_flow = ControlFlow::Wait; 154 155 match event { 156 Event::LoopDestroyed => (), 157 Event::WindowEvent { event, .. } => match event { 158 WindowEvent::Resized(physical_size) => windowed_context.resize(physical_size), 159 WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, 160 _ => (), 161 }, 162 Event::RedrawRequested(_) => { 163 let size = windowed_context.window().inner_size(); 164 let scale_factor = windowed_context.window().scale_factor(); 165 gl.draw_frame( 166 size.width as f32, 167 size.height as f32, 168 [0., 0., 0., 1.0], 169 [1., 1., 1., 1.0], 170 scale_factor as f32, 171 ); 172 windowed_context.swap_buffers().unwrap(); 173 } 174 _ => (), 175 } 176 }); 177 }