Compute shelf height properly
This commit is contained in:
parent
8033149e8b
commit
bc6efc9b62
|
@ -40,7 +40,6 @@ const ATLAS_SIZE: u32 = 2048;
|
||||||
const WIDTH: u32 = 640;
|
const WIDTH: u32 = 640;
|
||||||
const HEIGHT: u32 = 480;
|
const HEIGHT: u32 = 480;
|
||||||
const SCROLL_SPEED: f64 = 6.0;
|
const SCROLL_SPEED: f64 = 6.0;
|
||||||
const UNITS_PER_EM: u32 = 2048;
|
|
||||||
|
|
||||||
const INITIAL_POINT_SIZE: f32 = 24.0;
|
const INITIAL_POINT_SIZE: f32 = 24.0;
|
||||||
const MIN_POINT_SIZE: f32 = 6.0;
|
const MIN_POINT_SIZE: f32 = 6.0;
|
||||||
|
@ -102,12 +101,12 @@ fn main() {
|
||||||
shaped_glyph_positions = shaper::shape_text(&font, &glyph_ranges, &text)
|
shaped_glyph_positions = shaper::shape_text(&font, &glyph_ranges, &text)
|
||||||
}
|
}
|
||||||
|
|
||||||
let paragraph_width = (device_pixel_size.width as f32 * UNITS_PER_EM as f32 /
|
let paragraph_width = (device_pixel_size.width as f32 * font.units_per_em() as f32 /
|
||||||
INITIAL_POINT_SIZE) as u32;
|
INITIAL_POINT_SIZE) as u32;
|
||||||
|
|
||||||
// Do some basic line breaking.
|
// Do some basic line breaking.
|
||||||
let mut glyph_positions = vec![];
|
let mut glyph_positions = vec![];
|
||||||
let line_spacing = UNITS_PER_EM;
|
let line_spacing = font.units_per_em() as u32;
|
||||||
let (mut current_x, mut current_y) = (0, line_spacing);
|
let (mut current_x, mut current_y) = (0, line_spacing);
|
||||||
for glyph_position in &shaped_glyph_positions {
|
for glyph_position in &shaped_glyph_positions {
|
||||||
current_x += glyph_position.advance as u32;
|
current_x += glyph_position.advance as u32;
|
||||||
|
@ -136,11 +135,15 @@ fn main() {
|
||||||
|
|
||||||
let outline_buffers = outline_builder.create_buffers().unwrap();
|
let outline_buffers = outline_builder.create_buffers().unwrap();
|
||||||
|
|
||||||
let mut fps_atlas = renderer.create_fps_atlas(&outline_builder, &outline_buffers, glyph_count);
|
let mut fps_atlas = renderer.create_fps_atlas(&font,
|
||||||
|
&outline_builder,
|
||||||
|
&outline_buffers,
|
||||||
|
glyph_count);
|
||||||
|
|
||||||
while !window.should_close() {
|
while !window.should_close() {
|
||||||
if dirty {
|
if dirty {
|
||||||
let events = renderer.redraw(point_size,
|
let events = renderer.redraw(point_size,
|
||||||
|
&font,
|
||||||
&outline_builder,
|
&outline_builder,
|
||||||
&outline_buffers,
|
&outline_buffers,
|
||||||
glyph_count,
|
glyph_count,
|
||||||
|
@ -232,9 +235,8 @@ struct Renderer {
|
||||||
composite_translation_uniform: GLint,
|
composite_translation_uniform: GLint,
|
||||||
composite_color_uniform: GLint,
|
composite_color_uniform: GLint,
|
||||||
|
|
||||||
composite_vertex_array: GLuint,
|
main_composite_vertex_array: CompositeVertexArray,
|
||||||
composite_vertex_buffer: GLuint,
|
fps_composite_vertex_array: CompositeVertexArray,
|
||||||
composite_index_buffer: GLuint,
|
|
||||||
|
|
||||||
solid_color_program: GLuint,
|
solid_color_program: GLuint,
|
||||||
solid_color_color_uniform: GLint,
|
solid_color_color_uniform: GLint,
|
||||||
|
@ -245,7 +247,8 @@ struct Renderer {
|
||||||
|
|
||||||
atlas_size: Size2D<u32>,
|
atlas_size: Size2D<u32>,
|
||||||
|
|
||||||
coverage_buffer: CoverageBuffer,
|
main_coverage_buffer: CoverageBuffer,
|
||||||
|
fps_coverage_buffer: CoverageBuffer,
|
||||||
main_compute_image: Image,
|
main_compute_image: Image,
|
||||||
main_gl_texture: GLuint,
|
main_gl_texture: GLuint,
|
||||||
fps_compute_image: Image,
|
fps_compute_image: Image,
|
||||||
|
@ -266,10 +269,10 @@ impl Renderer {
|
||||||
let (composite_program, composite_position_attribute, composite_tex_coord_attribute);
|
let (composite_program, composite_position_attribute, composite_tex_coord_attribute);
|
||||||
let (composite_atlas_uniform, composite_transform_uniform);
|
let (composite_atlas_uniform, composite_transform_uniform);
|
||||||
let (composite_translation_uniform, composite_color_uniform);
|
let (composite_translation_uniform, composite_color_uniform);
|
||||||
|
let (main_composite_vertex_array, fps_composite_vertex_array);
|
||||||
let (solid_color_program, solid_color_position_attribute, solid_color_color_uniform);
|
let (solid_color_program, solid_color_position_attribute, solid_color_color_uniform);
|
||||||
let (mut composite_vertex_array, mut solid_color_vertex_array) = (0, 0);
|
|
||||||
let (mut composite_vertex_buffer, mut composite_index_buffer) = (0, 0);
|
|
||||||
let (mut solid_color_vertex_buffer, mut solid_color_index_buffer) = (0, 0);
|
let (mut solid_color_vertex_buffer, mut solid_color_index_buffer) = (0, 0);
|
||||||
|
let mut solid_color_vertex_array = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
composite_program = create_program(COMPOSITE_VERTEX_SHADER, COMPOSITE_FRAGMENT_SHADER);
|
composite_program = create_program(COMPOSITE_VERTEX_SHADER, COMPOSITE_FRAGMENT_SHADER);
|
||||||
composite_position_attribute =
|
composite_position_attribute =
|
||||||
|
@ -297,14 +300,13 @@ impl Renderer {
|
||||||
|
|
||||||
gl::UseProgram(composite_program);
|
gl::UseProgram(composite_program);
|
||||||
|
|
||||||
gl::GenVertexArrays(1, &mut composite_vertex_array);
|
main_composite_vertex_array = CompositeVertexArray::new();
|
||||||
gl::BindVertexArray(composite_vertex_array);
|
fps_composite_vertex_array = CompositeVertexArray::new();
|
||||||
|
for vertex_array in &[&main_composite_vertex_array, &fps_composite_vertex_array] {
|
||||||
|
gl::BindVertexArray(vertex_array.vertex_array);
|
||||||
|
|
||||||
gl::GenBuffers(1, &mut composite_vertex_buffer);
|
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, vertex_array.index_buffer);
|
||||||
gl::GenBuffers(1, &mut composite_index_buffer);
|
gl::BindBuffer(gl::ARRAY_BUFFER, vertex_array.vertex_buffer);
|
||||||
|
|
||||||
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, composite_index_buffer);
|
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, composite_vertex_buffer);
|
|
||||||
|
|
||||||
gl::VertexAttribPointer(composite_position_attribute as GLuint,
|
gl::VertexAttribPointer(composite_position_attribute as GLuint,
|
||||||
2,
|
2,
|
||||||
|
@ -320,6 +322,7 @@ impl Renderer {
|
||||||
(mem::size_of::<f32>() * 2) as *const GLvoid);
|
(mem::size_of::<f32>() * 2) as *const GLvoid);
|
||||||
gl::EnableVertexAttribArray(composite_position_attribute as GLuint);
|
gl::EnableVertexAttribArray(composite_position_attribute as GLuint);
|
||||||
gl::EnableVertexAttribArray(composite_tex_coord_attribute as GLuint);
|
gl::EnableVertexAttribArray(composite_tex_coord_attribute as GLuint);
|
||||||
|
}
|
||||||
|
|
||||||
gl::UseProgram(solid_color_program);
|
gl::UseProgram(solid_color_program);
|
||||||
|
|
||||||
|
@ -349,7 +352,8 @@ impl Renderer {
|
||||||
// FIXME(pcwalton)
|
// FIXME(pcwalton)
|
||||||
let atlas_size = Size2D::new(ATLAS_SIZE, ATLAS_SIZE);
|
let atlas_size = Size2D::new(ATLAS_SIZE, ATLAS_SIZE);
|
||||||
|
|
||||||
let coverage_buffer = CoverageBuffer::new(&rasterizer.device, &atlas_size).unwrap();
|
let main_coverage_buffer = CoverageBuffer::new(&rasterizer.device, &atlas_size).unwrap();
|
||||||
|
let fps_coverage_buffer = CoverageBuffer::new(&rasterizer.device, &atlas_size).unwrap();
|
||||||
|
|
||||||
let (main_compute_image, main_gl_texture) = create_image(&rasterizer, &atlas_size);
|
let (main_compute_image, main_gl_texture) = create_image(&rasterizer, &atlas_size);
|
||||||
let (fps_compute_image, fps_gl_texture) = create_image(&rasterizer, &atlas_size);
|
let (fps_compute_image, fps_gl_texture) = create_image(&rasterizer, &atlas_size);
|
||||||
|
@ -368,9 +372,8 @@ impl Renderer {
|
||||||
composite_translation_uniform: composite_translation_uniform,
|
composite_translation_uniform: composite_translation_uniform,
|
||||||
composite_color_uniform: composite_color_uniform,
|
composite_color_uniform: composite_color_uniform,
|
||||||
|
|
||||||
composite_vertex_array: composite_vertex_array,
|
main_composite_vertex_array: main_composite_vertex_array,
|
||||||
composite_vertex_buffer: composite_vertex_buffer,
|
fps_composite_vertex_array: fps_composite_vertex_array,
|
||||||
composite_index_buffer: composite_index_buffer,
|
|
||||||
|
|
||||||
solid_color_program: solid_color_program,
|
solid_color_program: solid_color_program,
|
||||||
solid_color_color_uniform: solid_color_color_uniform,
|
solid_color_color_uniform: solid_color_color_uniform,
|
||||||
|
@ -381,7 +384,8 @@ impl Renderer {
|
||||||
|
|
||||||
atlas_size: atlas_size,
|
atlas_size: atlas_size,
|
||||||
|
|
||||||
coverage_buffer: coverage_buffer,
|
main_coverage_buffer: main_coverage_buffer,
|
||||||
|
fps_coverage_buffer: fps_coverage_buffer,
|
||||||
main_compute_image: main_compute_image,
|
main_compute_image: main_compute_image,
|
||||||
main_gl_texture: main_gl_texture,
|
main_gl_texture: main_gl_texture,
|
||||||
fps_compute_image: fps_compute_image,
|
fps_compute_image: fps_compute_image,
|
||||||
|
@ -393,6 +397,7 @@ impl Renderer {
|
||||||
|
|
||||||
fn redraw(&self,
|
fn redraw(&self,
|
||||||
point_size: f32,
|
point_size: f32,
|
||||||
|
font: &Font,
|
||||||
outline_builder: &OutlineBuilder,
|
outline_builder: &OutlineBuilder,
|
||||||
outline_buffers: &OutlineBuffers,
|
outline_buffers: &OutlineBuffers,
|
||||||
glyph_count: usize,
|
glyph_count: usize,
|
||||||
|
@ -400,9 +405,7 @@ impl Renderer {
|
||||||
device_pixel_size: &Size2D<u32>,
|
device_pixel_size: &Size2D<u32>,
|
||||||
translation: &Point2D<i32>)
|
translation: &Point2D<i32>)
|
||||||
-> DrawAtlasProfilingEvents {
|
-> DrawAtlasProfilingEvents {
|
||||||
// FIXME(pcwalton)
|
let shelf_height = font.shelf_height(point_size);
|
||||||
let shelf_height = (point_size * 2.0).ceil() as u32;
|
|
||||||
|
|
||||||
let mut atlas_builder = AtlasBuilder::new(ATLAS_SIZE, shelf_height);
|
let mut atlas_builder = AtlasBuilder::new(ATLAS_SIZE, shelf_height);
|
||||||
for glyph_index in 0..(glyph_count as u32) {
|
for glyph_index in 0..(glyph_count as u32) {
|
||||||
atlas_builder.pack_glyph(&outline_builder, glyph_index, point_size).unwrap()
|
atlas_builder.pack_glyph(&outline_builder, glyph_index, point_size).unwrap()
|
||||||
|
@ -416,7 +419,7 @@ impl Renderer {
|
||||||
&rect,
|
&rect,
|
||||||
&atlas,
|
&atlas,
|
||||||
outline_buffers,
|
outline_buffers,
|
||||||
&self.coverage_buffer).unwrap();
|
&self.main_coverage_buffer).unwrap();
|
||||||
self.rasterizer.queue.flush().unwrap();
|
self.rasterizer.queue.flush().unwrap();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -428,8 +431,10 @@ impl Renderer {
|
||||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.draw_glyphs(&mut atlas_builder,
|
self.draw_glyphs(&font,
|
||||||
|
&mut atlas_builder,
|
||||||
outline_builder,
|
outline_builder,
|
||||||
|
&self.main_composite_vertex_array,
|
||||||
glyph_positions,
|
glyph_positions,
|
||||||
device_pixel_size,
|
device_pixel_size,
|
||||||
translation,
|
translation,
|
||||||
|
@ -449,8 +454,10 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_glyphs(&self,
|
fn draw_glyphs(&self,
|
||||||
|
font: &Font,
|
||||||
atlas_builder: &mut AtlasBuilder,
|
atlas_builder: &mut AtlasBuilder,
|
||||||
outline_builder: &OutlineBuilder,
|
outline_builder: &OutlineBuilder,
|
||||||
|
vertex_array: &CompositeVertexArray,
|
||||||
glyph_positions: &[GlyphPos],
|
glyph_positions: &[GlyphPos],
|
||||||
device_pixel_size: &Size2D<u32>,
|
device_pixel_size: &Size2D<u32>,
|
||||||
translation: &Point2D<i32>,
|
translation: &Point2D<i32>,
|
||||||
|
@ -459,11 +466,12 @@ impl Renderer {
|
||||||
color: &[f32]) {
|
color: &[f32]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::UseProgram(self.composite_program);
|
gl::UseProgram(self.composite_program);
|
||||||
gl::BindVertexArray(self.composite_vertex_array);
|
gl::BindVertexArray(vertex_array.vertex_array);
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, self.composite_vertex_buffer);
|
gl::BindBuffer(gl::ARRAY_BUFFER, vertex_array.vertex_buffer);
|
||||||
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.composite_index_buffer);
|
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, vertex_array.index_buffer);
|
||||||
|
|
||||||
let vertex_count = self.upload_quads_for_text(atlas_builder,
|
let vertex_count = self.upload_quads_for_text(font,
|
||||||
|
atlas_builder,
|
||||||
outline_builder,
|
outline_builder,
|
||||||
glyph_positions,
|
glyph_positions,
|
||||||
point_size);
|
point_size);
|
||||||
|
@ -500,12 +508,13 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn upload_quads_for_text(&self,
|
fn upload_quads_for_text(&self,
|
||||||
|
font: &Font,
|
||||||
atlas_builder: &mut AtlasBuilder,
|
atlas_builder: &mut AtlasBuilder,
|
||||||
outline_builder: &OutlineBuilder,
|
outline_builder: &OutlineBuilder,
|
||||||
glyph_positions: &[GlyphPos],
|
glyph_positions: &[GlyphPos],
|
||||||
point_size: f32)
|
point_size: f32)
|
||||||
-> usize {
|
-> usize {
|
||||||
let pixels_per_unit = point_size as f32 / UNITS_PER_EM as f32;
|
let pixels_per_unit = point_size as f32 / font.units_per_em() as f32;
|
||||||
|
|
||||||
let (mut vertices, mut indices) = (vec![], vec![]);
|
let (mut vertices, mut indices) = (vec![], vec![]);
|
||||||
for position in glyph_positions {
|
for position in glyph_positions {
|
||||||
|
@ -548,13 +557,12 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_fps_atlas(&self,
|
fn create_fps_atlas(&self,
|
||||||
|
font: &Font,
|
||||||
outline_builder: &OutlineBuilder,
|
outline_builder: &OutlineBuilder,
|
||||||
outline_buffers: &OutlineBuffers,
|
outline_buffers: &OutlineBuffers,
|
||||||
glyph_count: usize)
|
glyph_count: usize)
|
||||||
-> AtlasBuilder {
|
-> AtlasBuilder {
|
||||||
// FIXME(pcwalton)
|
let shelf_height = font.shelf_height(FPS_DISPLAY_POINT_SIZE);
|
||||||
let shelf_height = (FPS_DISPLAY_POINT_SIZE * 2.0).ceil() as u32;
|
|
||||||
|
|
||||||
let mut atlas_builder = AtlasBuilder::new(ATLAS_SIZE, shelf_height);
|
let mut atlas_builder = AtlasBuilder::new(ATLAS_SIZE, shelf_height);
|
||||||
for glyph_index in 0..(glyph_count as u32) {
|
for glyph_index in 0..(glyph_count as u32) {
|
||||||
atlas_builder.pack_glyph(&outline_builder, glyph_index, FPS_DISPLAY_POINT_SIZE)
|
atlas_builder.pack_glyph(&outline_builder, glyph_index, FPS_DISPLAY_POINT_SIZE)
|
||||||
|
@ -569,7 +577,7 @@ impl Renderer {
|
||||||
&rect,
|
&rect,
|
||||||
&atlas,
|
&atlas,
|
||||||
outline_buffers,
|
outline_buffers,
|
||||||
&self.coverage_buffer).unwrap();
|
&self.fps_coverage_buffer).unwrap();
|
||||||
|
|
||||||
atlas_builder
|
atlas_builder
|
||||||
}
|
}
|
||||||
|
@ -633,8 +641,10 @@ impl Renderer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
self.draw_glyphs(atlas_builder,
|
self.draw_glyphs(font,
|
||||||
|
atlas_builder,
|
||||||
outline_builder,
|
outline_builder,
|
||||||
|
&self.fps_composite_vertex_array,
|
||||||
&fps_glyphs,
|
&fps_glyphs,
|
||||||
device_pixel_size,
|
device_pixel_size,
|
||||||
&Point2D::new(FPS_PADDING, device_pixel_size.height as i32 - FPS_PADDING),
|
&Point2D::new(FPS_PADDING, device_pixel_size.height as i32 - FPS_PADDING),
|
||||||
|
@ -701,6 +711,31 @@ struct GlyphPos {
|
||||||
glyph_id: u16,
|
glyph_id: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct CompositeVertexArray {
|
||||||
|
vertex_array: GLuint,
|
||||||
|
vertex_buffer: GLuint,
|
||||||
|
index_buffer: GLuint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompositeVertexArray {
|
||||||
|
fn new() -> CompositeVertexArray {
|
||||||
|
let (mut vertex_array, mut vertex_buffer, mut index_buffer) = (0, 0, 0);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl::GenVertexArrays(1, &mut vertex_array);
|
||||||
|
gl::GenBuffers(1, &mut vertex_buffer);
|
||||||
|
gl::GenBuffers(1, &mut index_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
CompositeVertexArray {
|
||||||
|
vertex_array: vertex_array,
|
||||||
|
vertex_buffer: vertex_buffer,
|
||||||
|
index_buffer: index_buffer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn create_program(vertex_shader_source: &str, fragment_shader_source: &str) -> GLuint {
|
fn create_program(vertex_shader_source: &str, fragment_shader_source: &str) -> GLuint {
|
||||||
unsafe {
|
unsafe {
|
||||||
let vertex_shader = gl::CreateShader(gl::VERTEX_SHADER);
|
let vertex_shader = gl::CreateShader(gl::VERTEX_SHADER);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
use byteorder::{BigEndian, ReadBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt};
|
||||||
use otf::{Error, FontTable};
|
use otf::{Error, FontTable};
|
||||||
|
use outline::GlyphBounds;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use util::Jump;
|
use util::Jump;
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ const MAGIC_NUMBER: u32 = 0x5f0f3cf5;
|
||||||
pub struct HeadTable {
|
pub struct HeadTable {
|
||||||
pub units_per_em: u16,
|
pub units_per_em: u16,
|
||||||
pub index_to_loc_format: i16,
|
pub index_to_loc_format: i16,
|
||||||
|
pub max_glyph_bounds: GlyphBounds,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeadTable {
|
impl HeadTable {
|
||||||
|
@ -43,11 +45,21 @@ impl HeadTable {
|
||||||
try!(reader.jump(mem::size_of::<u16>()).map_err(Error::eof));
|
try!(reader.jump(mem::size_of::<u16>()).map_err(Error::eof));
|
||||||
let units_per_em = try!(reader.read_u16::<BigEndian>().map_err(Error::eof));
|
let units_per_em = try!(reader.read_u16::<BigEndian>().map_err(Error::eof));
|
||||||
|
|
||||||
|
// Read the maximum bounds.
|
||||||
|
try!(reader.jump(mem::size_of::<i64>() * 2).map_err(Error::eof));
|
||||||
|
let x_min = try!(reader.read_i16::<BigEndian>().map_err(Error::eof));
|
||||||
|
let y_min = try!(reader.read_i16::<BigEndian>().map_err(Error::eof));
|
||||||
|
let x_max = try!(reader.read_i16::<BigEndian>().map_err(Error::eof));
|
||||||
|
let y_max = try!(reader.read_i16::<BigEndian>().map_err(Error::eof));
|
||||||
|
let max_glyph_bounds = GlyphBounds {
|
||||||
|
left: x_min as i32,
|
||||||
|
bottom: y_min as i32,
|
||||||
|
right: x_max as i32,
|
||||||
|
top: y_max as i32,
|
||||||
|
};
|
||||||
|
|
||||||
// Read the index-to-location format.
|
// Read the index-to-location format.
|
||||||
try!(reader.jump(mem::size_of::<i64>() * 2 +
|
try!(reader.jump(mem::size_of::<u16>() * 2 + mem::size_of::<i16>()).map_err(Error::eof));
|
||||||
mem::size_of::<i16>() * 4 +
|
|
||||||
mem::size_of::<u16>() * 2 +
|
|
||||||
mem::size_of::<i16>()).map_err(Error::eof));
|
|
||||||
let index_to_loc_format = try!(reader.read_i16::<BigEndian>().map_err(Error::eof));
|
let index_to_loc_format = try!(reader.read_i16::<BigEndian>().map_err(Error::eof));
|
||||||
|
|
||||||
// Check the glyph data format.
|
// Check the glyph data format.
|
||||||
|
@ -59,6 +71,7 @@ impl HeadTable {
|
||||||
Ok(HeadTable {
|
Ok(HeadTable {
|
||||||
units_per_em: units_per_em,
|
units_per_em: units_per_em,
|
||||||
index_to_loc_format: index_to_loc_format,
|
index_to_loc_format: index_to_loc_format,
|
||||||
|
max_glyph_bounds: max_glyph_bounds,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,6 +284,12 @@ impl<'a> Font<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn shelf_height(&self, point_size: f32) -> u32 {
|
||||||
|
let pixel_rect = self.head.max_glyph_bounds.pixel_rect(self.head.units_per_em, point_size);
|
||||||
|
pixel_rect.round_out().size.height as u32
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn units_per_em(&self) -> u16 {
|
pub fn units_per_em(&self) -> u16 {
|
||||||
self.head.units_per_em
|
self.head.units_per_em
|
||||||
|
|
|
@ -162,10 +162,7 @@ pub struct GlyphDescriptor {
|
||||||
impl GlyphDescriptor {
|
impl GlyphDescriptor {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pixel_rect(&self, point_size: f32) -> Rect<f32> {
|
fn pixel_rect(&self, point_size: f32) -> Rect<f32> {
|
||||||
let pixels_per_unit = point_size / self.units_per_em as f32;
|
self.bounds.pixel_rect(self.units_per_em as u16, point_size)
|
||||||
Rect::new(Point2D::new(self.bounds.left as f32, self.bounds.bottom as f32),
|
|
||||||
Size2D::new((self.bounds.right - self.bounds.left) as f32,
|
|
||||||
(self.bounds.top - self.bounds.bottom) as f32)) * pixels_per_unit
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,3 +184,13 @@ pub struct GlyphBounds {
|
||||||
pub top: i32,
|
pub top: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GlyphBounds {
|
||||||
|
#[inline]
|
||||||
|
pub fn pixel_rect(&self, units_per_em: u16, point_size: f32) -> Rect<f32> {
|
||||||
|
let pixels_per_unit = point_size / units_per_em as f32;
|
||||||
|
Rect::new(Point2D::new(self.left as f32, self.bottom as f32),
|
||||||
|
Size2D::new((self.right - self.left) as f32, (self.top - self.bottom) as f32)) *
|
||||||
|
pixels_per_unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue