autocommit 2022-04-01 01:44:10 CEST
This commit is contained in:
parent
ab4ac883ee
commit
2dd433aa04
32 changed files with 626 additions and 139 deletions
110
src/text.rs
110
src/text.rs
|
|
@ -2,9 +2,14 @@ use crate::format::ARGB8888;
|
|||
use crate::pango::consts::{
|
||||
CAIRO_FORMAT_ARGB32, CAIRO_OPERATOR_SOURCE, PANGO_ELLIPSIZE_END, PANGO_SCALE,
|
||||
};
|
||||
use crate::pango::{CairoImageSurface, PangoError, PangoFontDescription};
|
||||
use crate::pango::{
|
||||
CairoContext, CairoImageSurface, PangoCairoContext, PangoError, PangoFontDescription,
|
||||
PangoLayout,
|
||||
};
|
||||
use crate::rect::Rect;
|
||||
use crate::render::{RenderContext, RenderError, Texture};
|
||||
use crate::theme::Color;
|
||||
use std::ops::Neg;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
|
||||
|
|
@ -24,14 +29,15 @@ pub enum TextError {
|
|||
ImageData(#[source] PangoError),
|
||||
}
|
||||
|
||||
pub fn render(
|
||||
ctx: &Rc<RenderContext>,
|
||||
width: i32,
|
||||
height: i32,
|
||||
font: &str,
|
||||
text: &str,
|
||||
color: Color,
|
||||
) -> Result<Rc<Texture>, TextError> {
|
||||
struct Data {
|
||||
image: Rc<CairoImageSurface>,
|
||||
cctx: Rc<CairoContext>,
|
||||
_pctx: Rc<PangoCairoContext>,
|
||||
_fd: PangoFontDescription,
|
||||
layout: PangoLayout,
|
||||
}
|
||||
|
||||
fn create_data(font: &str, width: i32, height: i32) -> Result<Data, TextError> {
|
||||
let image = match CairoImageSurface::new_image_surface(CAIRO_FORMAT_ARGB32, width, height) {
|
||||
Ok(s) => s,
|
||||
Err(e) => return Err(TextError::CreateImage(e)),
|
||||
|
|
@ -49,22 +55,86 @@ pub fn render(
|
|||
Ok(l) => l,
|
||||
Err(e) => return Err(TextError::CreateLayout(e)),
|
||||
};
|
||||
layout.set_width((width - 2).max(0) * PANGO_SCALE);
|
||||
layout.set_ellipsize(PANGO_ELLIPSIZE_END);
|
||||
layout.set_font_description(&fd);
|
||||
layout.set_text(text);
|
||||
let font_height = layout.pixel_size().1;
|
||||
cctx.set_operator(CAIRO_OPERATOR_SOURCE);
|
||||
cctx.set_source_rgba(color.r as _, color.g as _, color.b as _, color.a as _);
|
||||
cctx.move_to(1.0, ((height - font_height) / 2) as f64);
|
||||
layout.show_layout();
|
||||
image.flush();
|
||||
let data = match image.data() {
|
||||
Ok(Data {
|
||||
image,
|
||||
cctx,
|
||||
_pctx: pctx,
|
||||
_fd: fd,
|
||||
layout,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn measure(font: &str, text: &str) -> Result<Rect, TextError> {
|
||||
let data = create_data(font, 1, 1)?;
|
||||
data.layout.set_text(text);
|
||||
Ok(data.layout.inc_pixel_rect())
|
||||
}
|
||||
|
||||
pub fn render(
|
||||
ctx: &Rc<RenderContext>,
|
||||
width: i32,
|
||||
height: i32,
|
||||
font: &str,
|
||||
text: &str,
|
||||
color: Color,
|
||||
) -> Result<Rc<Texture>, TextError> {
|
||||
render2(ctx, 1, width, height, 1, font, text, color, true)
|
||||
}
|
||||
|
||||
pub fn render2(
|
||||
ctx: &Rc<RenderContext>,
|
||||
x: i32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
padding: i32,
|
||||
font: &str,
|
||||
text: &str,
|
||||
color: Color,
|
||||
ellipsize: bool,
|
||||
) -> Result<Rc<Texture>, TextError> {
|
||||
let data = create_data(font, width, height)?;
|
||||
if ellipsize {
|
||||
data.layout
|
||||
.set_width((width - 2 * padding).max(0) * PANGO_SCALE);
|
||||
data.layout.set_ellipsize(PANGO_ELLIPSIZE_END);
|
||||
}
|
||||
data.layout.set_text(text);
|
||||
let font_height = data.layout.pixel_size().1;
|
||||
data.cctx.set_operator(CAIRO_OPERATOR_SOURCE);
|
||||
data.cctx
|
||||
.set_source_rgba(color.r as _, color.g as _, color.b as _, color.a as _);
|
||||
data.cctx
|
||||
.move_to(x as f64, ((height - font_height) / 2) as f64);
|
||||
data.layout.show_layout();
|
||||
data.image.flush();
|
||||
let bytes = match data.image.data() {
|
||||
Ok(d) => d,
|
||||
Err(e) => return Err(TextError::ImageData(e)),
|
||||
};
|
||||
match ctx.shmem_texture(data, ARGB8888, width, height, image.stride()) {
|
||||
match ctx.shmem_texture(bytes, ARGB8888, width, height, data.image.stride()) {
|
||||
Ok(t) => Ok(t),
|
||||
Err(e) => Err(TextError::RenderError(e)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_fitting(
|
||||
ctx: &Rc<RenderContext>,
|
||||
height: i32,
|
||||
font: &str,
|
||||
text: &str,
|
||||
color: Color,
|
||||
) -> Result<Rc<Texture>, TextError> {
|
||||
let rect = measure(font, text)?;
|
||||
render2(
|
||||
ctx,
|
||||
rect.x1().neg(),
|
||||
rect.width(),
|
||||
height,
|
||||
0,
|
||||
font,
|
||||
text,
|
||||
color,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue