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:
parent
2a7892e3c5
commit
389c477b16
@ -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,
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user