1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-23 23:21:08 +03:00

software: ligatures now render, but scaled emoji need work

This commit is contained in:
Wez Furlong 2019-09-28 10:06:47 -07:00
parent 2a7892e3c5
commit 389c477b16
3 changed files with 63 additions and 116 deletions

View File

@ -30,7 +30,6 @@ struct GlyphKey {
/// Caches a rendered glyph.
/// The image data may be None for whitespace glyphs.
struct CachedGlyph {
has_color: bool,
x_offset: f64,
y_offset: f64,
bearing_x: f64,
@ -581,55 +580,24 @@ impl TermWindow {
}
if let Some(ref texture) = glyph.texture {
let slice = SpriteSlice {
cell_idx: glyph_idx,
num_cells: info.num_cells as usize,
cell_width: self.cell_size.width as usize,
scale: glyph.scale as f32,
left_offset: left,
};
let left = if glyph_idx == 0 { left } else { 0.0 };
ctx.draw_image(
Point::new(
(cell_rect.origin.x as f32 + left) as isize,
(cell_rect.origin.y as f32 + top) as isize,
),
Some(texture.coords),
Some(slice.pixel_rect(texture)),
&*texture.texture.image.borrow(),
if glyph.has_color {
Operator::Source
} else {
Operator::MultiplyThenOver(glyph_color)
},
Operator::MultiplyThenOver(glyph_color),
);
/* TODO: SpriteSlice for double-width
let slice = SpriteSlice {
cell_idx: glyph_idx,
num_cells: info.num_cells as usize,
cell_width: self.cell_width.ceil() as usize,
scale: glyph.scale as f32,
left_offset: left,
};
// How much of the width of this glyph we can use here
let slice_width = texture.slice_width(&slice);
let left = if glyph_idx == 0 { left } else { 0.0 };
let right = (slice_width as f32 + left) - self.cell_width as f32;
let bottom = (texture.coords.height as f32 * glyph.scale as f32 + top)
- self.cell_height as f32;
vert[V_TOP_LEFT].tex = texture.top_left(&slice);
vert[V_TOP_LEFT].adjust = TexturePoint::new(left, top);
vert[V_TOP_RIGHT].tex = texture.top_right(&slice);
vert[V_TOP_RIGHT].adjust = TexturePoint::new(right, top);
vert[V_BOT_LEFT].tex = texture.bottom_left(&slice);
vert[V_BOT_LEFT].adjust = TexturePoint::new(left, bottom);
vert[V_BOT_RIGHT].tex = texture.bottom_right(&slice);
vert[V_BOT_RIGHT].adjust = TexturePoint::new(right, bottom);
let has_color = if glyph.has_color { 1.0 } else { 0.0 };
vert[V_TOP_LEFT].has_color = has_color;
vert[V_TOP_RIGHT].has_color = has_color;
vert[V_BOT_LEFT].has_color = has_color;
vert[V_BOT_RIGHT].has_color = has_color;
*/
}
}
}
@ -738,14 +706,13 @@ impl TermWindow {
/// Perform the load and render of a glyph
fn load_glyph(&self, info: &GlyphInfo, style: &TextStyle) -> Fallible<Rc<CachedGlyph>> {
let (has_color, glyph, cell_width, cell_height) = {
let (glyph, cell_width, cell_height) = {
let font = self.fonts.cached_font(style)?;
let mut font = font.borrow_mut();
let metrics = font.get_fallback(0)?.metrics();
let active_font = font.get_fallback(info.font_idx)?;
let has_color = active_font.has_color();
let glyph = active_font.rasterize_glyph(info.glyph_pos)?;
(has_color, glyph, metrics.cell_width, metrics.cell_height)
(glyph, metrics.cell_width, metrics.cell_height)
};
let scale = if (info.x_advance / f64::from(info.num_cells)).floor() > cell_width {
@ -766,7 +733,6 @@ impl TermWindow {
// a whitespace glyph
CachedGlyph {
texture: None,
has_color,
x_offset,
y_offset,
bearing_x: 0.0,
@ -774,7 +740,7 @@ impl TermWindow {
scale,
}
} else {
let raw_im = Image::with_bgra32(
let raw_im = Image::with_rgba32(
glyph.width as usize,
glyph.height as usize,
4 * glyph.width as usize,
@ -788,7 +754,6 @@ impl TermWindow {
CachedGlyph {
texture: Some(tex),
has_color,
x_offset,
y_offset,
bearing_x,

View File

@ -1,4 +1,4 @@
use crate::bitmaps::{BitmapImage, Texture2d};
use crate::bitmaps::{BitmapImage, Texture2d, TextureRect};
use crate::{Point, Rect, Size};
use failure::{ensure, Fallible};
use failure_derive::*;
@ -119,24 +119,13 @@ where
pub coords: Rect,
}
pub struct TextureUnit;
pub type TextureCoord = euclid::Point2D<f32, TextureUnit>;
pub type TextureRect = euclid::Rect<f32, TextureUnit>;
pub type TextureSize = euclid::Size2D<f32, TextureUnit>;
impl<T> Sprite<T>
where
T: Texture2d,
{
/// Returns the texture coordinates of the sprite
pub fn texture_coords(&self) -> TextureRect {
let coords = self.coords.to_f32();
let width = self.texture.width() as f32;
let height = self.texture.height() as f32;
TextureRect::new(
TextureCoord::new(coords.min_x() / width, coords.min_y() / height),
TextureSize::new(coords.size.width / width, coords.size.height / height),
)
self.texture.to_texture_coords(self.coords)
}
}
@ -161,6 +150,16 @@ pub struct SpriteSlice {
}
impl SpriteSlice {
pub fn pixel_rect<T: Texture2d>(&self, sprite: &Sprite<T>) -> Rect {
let width = self.slice_width(sprite) as isize;
let left = self.left_pix(sprite) as isize;
Rect::new(
Point::new(sprite.coords.origin.x + left, sprite.coords.origin.y),
Size::new(width, sprite.coords.size.height),
)
}
/// Returns the scaled offset to the left most pixel in a slice.
/// This is 0 for the first slice and increases by the slice_width
/// as we work through the slices.
@ -204,58 +203,4 @@ impl SpriteSlice {
self.cell_width as f32
}
}
/// Returns the left coordinate for a slice in texture coordinate space
#[inline]
fn left<T: Texture2d>(&self, sprite: &Sprite<T>) -> f32 {
let left = sprite.coords.min_x() as f32 + (self.left_pix(sprite) / self.scale);
left / sprite.texture.width() as f32
}
/// Returns the right coordinate for a slice in texture coordinate space
#[inline]
fn right<T: Texture2d>(&self, sprite: &Sprite<T>) -> f32 {
let right = sprite.coords.min_x() as f32
+ ((self.left_pix(sprite) + self.slice_width(sprite)) as f32 / self.scale);
right / sprite.texture.width() as f32
}
/// Returns the top coordinate for a slice in texture coordinate space
#[inline]
fn top<T: Texture2d>(&self, sprite: &Sprite<T>) -> f32 {
sprite.coords.max_y() as f32 / sprite.texture.height() as f32
}
/// Returns the bottom coordinate for a slice in texture coordinate space
#[inline]
fn bottom<T: Texture2d>(&self, sprite: &Sprite<T>) -> f32 {
(sprite.coords.max_y() + sprite.coords.size.height as isize) as f32
/ sprite.texture.height() as f32
}
/// Returns the top-left coordinate for a slice in texture coordinate space
#[inline]
pub fn top_left<T: Texture2d>(&self, sprite: &Sprite<T>) -> TextureCoord {
TextureCoord::new(self.left(sprite), self.top(sprite))
}
/// Returns the bottom-left coordinate for a slice in texture coordinate
/// space
#[inline]
pub fn bottom_left<T: Texture2d>(&self, sprite: &Sprite<T>) -> TextureCoord {
TextureCoord::new(self.left(sprite), self.bottom(sprite))
}
/// Returns the bottom-right coordinate for a slice in texture coordinate
/// space
#[inline]
pub fn bottom_right<T: Texture2d>(&self, sprite: &Sprite<T>) -> TextureCoord {
TextureCoord::new(self.right(sprite), self.bottom(sprite))
}
/// Returns the top-right coordinate for a slice in texture coordinate space
#[inline]
pub fn top_right<T: Texture2d>(&self, sprite: &Sprite<T>) -> TextureCoord {
TextureCoord::new(self.right(sprite), self.top(sprite))
}
}

View File

@ -5,6 +5,11 @@ use std::cell::RefCell;
pub mod atlas;
pub struct TextureUnit;
pub type TextureCoord = euclid::Point2D<f32, TextureUnit>;
pub type TextureRect = euclid::Rect<f32, TextureUnit>;
pub type TextureSize = euclid::Size2D<f32, TextureUnit>;
/// Represents a big endian bgra32 bitmap that may not be present
/// in local RAM, but may be addressable in eg: video RAM
pub trait Texture2d {
@ -23,6 +28,17 @@ pub trait Texture2d {
/// Returns the height of the texture in pixels
fn height(&self) -> usize;
/// Converts a rect in pixel coordinates to texture coordinates
fn to_texture_coords(&self, coords: Rect) -> TextureRect {
let coords = coords.to_f32();
let width = self.width() as f32;
let height = self.height() as f32;
TextureRect::new(
TextureCoord::new(coords.min_x() / width, coords.min_y() / height),
TextureSize::new(coords.size.width / width, coords.size.height / height),
)
}
}
/// A bitmap in big endian bgra32 color format with abstract
@ -277,6 +293,27 @@ impl Image {
image
}
/// Create a new bgra32 image buffer with the specified dimensions.
/// The buffer is populated with the source data in rgba32 format.
pub fn with_rgba32(width: usize, height: usize, stride: usize, data: &[u8]) -> Image {
let mut image = Image::new(width, height);
for y in 0..height {
let src_offset = y * stride;
let dest_offset = y * width * 4;
for x in 0..width {
let red = data[src_offset + (x * 4) + 0];
let green = data[src_offset + (x * 4) + 1];
let blue = data[src_offset + (x * 4) + 2];
let alpha = data[src_offset + (x * 4) + 3];
image.data[dest_offset + (x * 4) + 0] = blue;
image.data[dest_offset + (x * 4) + 1] = green;
image.data[dest_offset + (x * 4) + 2] = red;
image.data[dest_offset + (x * 4) + 3] = alpha;
}
}
image
}
pub fn with_8bpp(width: usize, height: usize, stride: usize, data: &[u8]) -> Image {
let mut image = Image::new(width, height);
for y in 0..height {