autocommit 2022-03-23 15:56:15 CET
This commit is contained in:
parent
63be47a9fb
commit
5e9e8c3a94
9 changed files with 479 additions and 290 deletions
|
|
@ -186,15 +186,15 @@ macro_rules! linear_ids {
|
|||
macro_rules! cenum {
|
||||
($name:ident, $uc:ident; $($name2:ident = $val:expr,)*) => {
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct $name(pub(super) u32);
|
||||
pub struct $name(pub(super) i32);
|
||||
|
||||
impl $name {
|
||||
pub fn raw(self) -> u32 {
|
||||
pub fn raw(self) -> i32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub const $uc: &[u32] = &[$($val,)*];
|
||||
pub const $uc: &[i32] = &[$($val,)*];
|
||||
|
||||
$(
|
||||
pub const $name2: $name = $name($val);
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ mod wire_xcon;
|
|||
mod xcon;
|
||||
mod xkbcommon;
|
||||
mod xwayland;
|
||||
mod pango;
|
||||
|
||||
fn main() {
|
||||
env_logger::builder()
|
||||
|
|
|
|||
317
src/pango.rs
Normal file
317
src/pango.rs
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::{c, IntoUstr};
|
||||
use crate::pango::consts::{CairoFormat, CairoOperator, PangoEllipsizeMode};
|
||||
|
||||
pub mod consts;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/pango_tys.rs"));
|
||||
|
||||
#[link(name = "cairo")]
|
||||
extern {
|
||||
type cairo_surface_t;
|
||||
type cairo_t;
|
||||
|
||||
fn cairo_image_surface_create(
|
||||
format: cairo_format_t,
|
||||
width: c::c_int,
|
||||
height: c::c_int,
|
||||
) -> *mut cairo_surface_t;
|
||||
fn cairo_image_surface_get_height(surface: *mut cairo_surface_t) -> c::c_int;
|
||||
fn cairo_image_surface_get_stride(surface: *mut cairo_surface_t) -> c::c_int;
|
||||
fn cairo_image_surface_get_data(surface: *mut cairo_surface_t) -> *mut u8;
|
||||
|
||||
fn cairo_surface_destroy(surface: *mut cairo_surface_t);
|
||||
fn cairo_surface_status(surface: *mut cairo_surface_t) -> cairo_status_t;
|
||||
fn cairo_surface_flush(surface: *mut cairo_surface_t);
|
||||
|
||||
fn cairo_create(surface: *mut cairo_surface_t) -> *mut cairo_t;
|
||||
fn cairo_status(cairo: *mut cairo_t) -> cairo_status_t;
|
||||
fn cairo_destroy(cairo: *mut cairo_t);
|
||||
|
||||
fn cairo_set_operator(cr: *mut cairo_t, op: cairo_operator_t);
|
||||
fn cairo_set_source_rgba(
|
||||
cr: *mut cairo_t,
|
||||
red: f64,
|
||||
green: f64,
|
||||
blue: f64,
|
||||
alpha: f64,
|
||||
);
|
||||
fn cairo_move_to(cr: *mut cairo_t, x: f64, y: f64);
|
||||
}
|
||||
|
||||
#[link(name = "pangocairo-1.0")]
|
||||
extern {
|
||||
type PangoContext_;
|
||||
|
||||
fn pango_cairo_create_context(cr: *mut cairo_t) -> *mut PangoContext_;
|
||||
fn pango_cairo_show_layout(cr: *mut cairo_t, layout: *mut PangoLayout_);
|
||||
}
|
||||
|
||||
#[link(name = "gobject-2.0")]
|
||||
extern {
|
||||
type GObject;
|
||||
|
||||
fn g_object_unref(object: *mut GObject);
|
||||
}
|
||||
|
||||
#[link(name = "pango-1.0")]
|
||||
extern {
|
||||
type PangoFontDescription_;
|
||||
type PangoLayout_;
|
||||
|
||||
fn pango_font_description_from_string(str: *const c::c_char) -> *mut PangoFontDescription_;
|
||||
fn pango_font_description_free(desc: *mut PangoFontDescription_);
|
||||
|
||||
fn pango_layout_new(context: *mut PangoContext_) -> *mut PangoLayout_;
|
||||
fn pango_layout_set_width(layout: *mut PangoLayout_, width: c::c_int);
|
||||
fn pango_layout_set_ellipsize(layout: *mut PangoLayout_, ellipsize: PangoEllipsizeMode_);
|
||||
fn pango_layout_set_font_description(
|
||||
layout: *mut PangoLayout_,
|
||||
desc: *const PangoFontDescription_,
|
||||
);
|
||||
fn pango_layout_set_text(layout: *mut PangoLayout_, text: *const c::c_char, length: c::c_int);
|
||||
fn pango_layout_get_pixel_size(
|
||||
layout: *mut PangoLayout_,
|
||||
width: *mut c::c_int,
|
||||
height: *mut c::c_int,
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PangoError {
|
||||
#[error("Could not create an image surface: {0}")]
|
||||
CreateSurface(u32),
|
||||
#[error("Could not create a cairo context: {0}")]
|
||||
CreateCairo(u32),
|
||||
#[error("Could not create a pangocairo context")]
|
||||
CreatePangoCairo,
|
||||
#[error("Could not create a pango layout")]
|
||||
CreateLayout,
|
||||
#[error("Could not retrieve image data")]
|
||||
GetData,
|
||||
}
|
||||
|
||||
pub struct CairoImageSurface {
|
||||
s: *mut cairo_surface_t,
|
||||
}
|
||||
|
||||
impl CairoImageSurface {
|
||||
pub fn new_image_surface(format: CairoFormat, width: i32, height: i32) -> Result<Rc<Self>, PangoError> {
|
||||
unsafe {
|
||||
let s = cairo_image_surface_create(format.raw() as _, width as _, height as _);
|
||||
let status = cairo_surface_status(s);
|
||||
if status != 0 {
|
||||
return Err(PangoError::CreateSurface(status as _));
|
||||
}
|
||||
Ok(Rc::new(Self {
|
||||
s,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_context(self: &Rc<Self>) -> Result<Rc<CairoContext>, PangoError> {
|
||||
unsafe {
|
||||
let c = cairo_create(self.s);
|
||||
let status = cairo_status(c);
|
||||
if status != 0 {
|
||||
return Err(PangoError::CreateCairo(status as _));
|
||||
}
|
||||
Ok(Rc::new(CairoContext {
|
||||
_s: self.clone(),
|
||||
c,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flush(&self) {
|
||||
unsafe {
|
||||
cairo_surface_flush(self.s);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn height(&self) -> i32 {
|
||||
unsafe {
|
||||
cairo_image_surface_get_height(self.s) as _
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stride(&self) -> i32 {
|
||||
unsafe {
|
||||
cairo_image_surface_get_stride(self.s) as _
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data(&self) -> Result<&[Cell<u8>], PangoError> {
|
||||
unsafe {
|
||||
let d = cairo_image_surface_get_data(self.s);
|
||||
if d.is_null() {
|
||||
return Err(PangoError::GetData);
|
||||
}
|
||||
let size = self.height() as usize * self.stride() as usize;
|
||||
Ok(std::slice::from_raw_parts(d.cast(), size))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for CairoImageSurface {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
cairo_surface_destroy(self.s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CairoContext {
|
||||
_s: Rc<CairoImageSurface>,
|
||||
c: *mut cairo_t,
|
||||
}
|
||||
|
||||
impl CairoContext {
|
||||
pub fn create_pango_context(self: &Rc<Self>) -> Result<Rc<PangoCairoContext>, PangoError> {
|
||||
unsafe {
|
||||
let p = pango_cairo_create_context(self.c);
|
||||
if p.is_null() {
|
||||
return Err(PangoError::CreatePangoCairo);
|
||||
}
|
||||
Ok(Rc::new(PangoCairoContext {
|
||||
c: self.clone(),
|
||||
p,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_operator(&self, op: CairoOperator) {
|
||||
unsafe {
|
||||
cairo_set_operator(self.c, op.raw() as _);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_source_rgba(&self, r: f64, g: f64, b: f64, a: f64) {
|
||||
unsafe {
|
||||
cairo_set_source_rgba(self.c, r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn move_to(&self, x: f64, y: f64) {
|
||||
unsafe {
|
||||
cairo_move_to(self.c, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for CairoContext {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
cairo_destroy(self.c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PangoCairoContext {
|
||||
c: Rc<CairoContext>,
|
||||
p: *mut PangoContext_,
|
||||
}
|
||||
|
||||
impl PangoCairoContext {
|
||||
pub fn create_layout(self: &Rc<Self>) -> Result<PangoLayout, PangoError> {
|
||||
unsafe {
|
||||
let l = pango_layout_new(self.p as _);
|
||||
if l.is_null() {
|
||||
return Err(PangoError::CreateLayout);
|
||||
}
|
||||
Ok(PangoLayout {
|
||||
c: self.clone(),
|
||||
l: l,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PangoCairoContext {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
g_object_unref(self.p as _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PangoFontDescription {
|
||||
s: *mut PangoFontDescription_,
|
||||
}
|
||||
|
||||
impl PangoFontDescription {
|
||||
pub fn from_string<'a>(s: impl IntoUstr<'a>) -> Self {
|
||||
let s = s.into_ustr();
|
||||
Self {
|
||||
s: unsafe {
|
||||
pango_font_description_from_string(s.as_ptr())
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PangoFontDescription {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
pango_font_description_free(self.s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PangoLayout {
|
||||
c: Rc<PangoCairoContext>,
|
||||
l: *mut PangoLayout_,
|
||||
}
|
||||
|
||||
impl PangoLayout {
|
||||
pub fn set_width(&self, width: i32) {
|
||||
unsafe {
|
||||
pango_layout_set_width(self.l, width as _);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_ellipsize(&self, ellipsize: PangoEllipsizeMode) {
|
||||
unsafe {
|
||||
pango_layout_set_ellipsize(self.l, ellipsize.raw() as _);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_font_description(&self, fd: &PangoFontDescription) {
|
||||
unsafe {
|
||||
pango_layout_set_font_description(self.l, fd.s);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_text(&self, text: &str) {
|
||||
unsafe {
|
||||
pango_layout_set_text(self.l, text.as_ptr() as _, text.len() as _);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pixel_size(&self) -> (i32, i32) {
|
||||
unsafe {
|
||||
let mut w = 0;
|
||||
let mut h = 0;
|
||||
pango_layout_get_pixel_size(self.l, &mut w, &mut h);
|
||||
(w as _, h as _)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show_layout(&self) {
|
||||
unsafe {
|
||||
pango_cairo_show_layout(self.c.c.c, self.l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PangoLayout {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
g_object_unref(self.l as _);
|
||||
}
|
||||
}
|
||||
}
|
||||
109
src/pango/consts.rs
Normal file
109
src/pango/consts.rs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
cenum! {
|
||||
CairoFormat, CAIRO_FORMATS;
|
||||
|
||||
CAIRO_FORMAT_INVALID = -1,
|
||||
CAIRO_FORMAT_ARGB32 = 0,
|
||||
CAIRO_FORMAT_RGB24 = 1,
|
||||
CAIRO_FORMAT_A8 = 2,
|
||||
CAIRO_FORMAT_A1 = 3,
|
||||
CAIRO_FORMAT_RGB16_565 = 4,
|
||||
CAIRO_FORMAT_RGB30 = 5,
|
||||
CAIRO_FORMAT_RGB96F = 6,
|
||||
CAIRO_FORMAT_RGBA128F = 7,
|
||||
}
|
||||
|
||||
cenum! {
|
||||
CairoStatus, CAIRO_STATUSES;
|
||||
|
||||
CAIRO_STATUS_SUCCESS = 0,
|
||||
CAIRO_STATUS_NO_MEMORY = 1,
|
||||
CAIRO_STATUS_INVALID_RESTORE = 2,
|
||||
CAIRO_STATUS_INVALID_POP_GROUP = 3,
|
||||
CAIRO_STATUS_NO_CURRENT_POINT = 4,
|
||||
CAIRO_STATUS_INVALID_MATRIX = 5,
|
||||
CAIRO_STATUS_INVALID_STATUS = 6,
|
||||
CAIRO_STATUS_NULL_POINTER = 7,
|
||||
CAIRO_STATUS_INVALID_STRING = 8,
|
||||
CAIRO_STATUS_INVALID_PATH_DATA = 9,
|
||||
CAIRO_STATUS_READ_ERROR = 10,
|
||||
CAIRO_STATUS_WRITE_ERROR = 11,
|
||||
CAIRO_STATUS_SURFACE_FINISHED = 12,
|
||||
CAIRO_STATUS_SURFACE_TYPE_MISMATCH = 13,
|
||||
CAIRO_STATUS_PATTERN_TYPE_MISMATCH = 14,
|
||||
CAIRO_STATUS_INVALID_CONTENT = 15,
|
||||
CAIRO_STATUS_INVALID_FORMAT = 16,
|
||||
CAIRO_STATUS_INVALID_VISUAL = 17,
|
||||
CAIRO_STATUS_FILE_NOT_FOUND = 18,
|
||||
CAIRO_STATUS_INVALID_DASH = 19,
|
||||
CAIRO_STATUS_INVALID_DSC_COMMENT = 20,
|
||||
CAIRO_STATUS_INVALID_INDEX = 21,
|
||||
CAIRO_STATUS_CLIP_NOT_REPRESENTABLE = 22,
|
||||
CAIRO_STATUS_TEMP_FILE_ERROR = 23,
|
||||
CAIRO_STATUS_INVALID_STRIDE = 24,
|
||||
CAIRO_STATUS_FONT_TYPE_MISMATCH = 25,
|
||||
CAIRO_STATUS_USER_FONT_IMMUTABLE = 26,
|
||||
CAIRO_STATUS_USER_FONT_ERROR = 27,
|
||||
CAIRO_STATUS_NEGATIVE_COUNT = 28,
|
||||
CAIRO_STATUS_INVALID_CLUSTERS = 29,
|
||||
CAIRO_STATUS_INVALID_SLANT = 30,
|
||||
CAIRO_STATUS_INVALID_WEIGHT = 31,
|
||||
CAIRO_STATUS_INVALID_SIZE = 32,
|
||||
CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED = 33,
|
||||
CAIRO_STATUS_DEVICE_TYPE_MISMATCH = 34,
|
||||
CAIRO_STATUS_DEVICE_ERROR = 35,
|
||||
CAIRO_STATUS_INVALID_MESH_CONSTRUCTION = 36,
|
||||
CAIRO_STATUS_DEVICE_FINISHED = 37,
|
||||
CAIRO_STATUS_JBIG2_GLOBAL_MISSING = 38,
|
||||
CAIRO_STATUS_PNG_ERROR = 39,
|
||||
CAIRO_STATUS_FREETYPE_ERROR = 40,
|
||||
CAIRO_STATUS_WIN32_GDI_ERROR = 41,
|
||||
CAIRO_STATUS_TAG_ERROR = 42,
|
||||
CAIRO_STATUS_LAST_STATUS = 43,
|
||||
}
|
||||
|
||||
cenum! {
|
||||
CairoOperator, CAIRO_OPERATORS;
|
||||
|
||||
CAIRO_OPERATOR_CLEAR = 0,
|
||||
CAIRO_OPERATOR_SOURCE = 1,
|
||||
CAIRO_OPERATOR_OVER = 2,
|
||||
CAIRO_OPERATOR_IN = 3,
|
||||
CAIRO_OPERATOR_OUT = 4,
|
||||
CAIRO_OPERATOR_ATOP = 5,
|
||||
CAIRO_OPERATOR_DEST = 6,
|
||||
CAIRO_OPERATOR_DEST_OVER = 7,
|
||||
CAIRO_OPERATOR_DEST_IN = 8,
|
||||
CAIRO_OPERATOR_DEST_OUT = 9,
|
||||
CAIRO_OPERATOR_DEST_ATOP = 10,
|
||||
CAIRO_OPERATOR_XOR = 11,
|
||||
CAIRO_OPERATOR_ADD = 12,
|
||||
CAIRO_OPERATOR_SATURATE = 13,
|
||||
CAIRO_OPERATOR_MULTIPLY = 14,
|
||||
CAIRO_OPERATOR_SCREEN = 15,
|
||||
CAIRO_OPERATOR_OVERLAY = 16,
|
||||
CAIRO_OPERATOR_DARKEN = 17,
|
||||
CAIRO_OPERATOR_LIGHTEN = 18,
|
||||
CAIRO_OPERATOR_COLOR_DODGE = 19,
|
||||
CAIRO_OPERATOR_COLOR_BURN = 20,
|
||||
CAIRO_OPERATOR_HARD_LIGHT = 21,
|
||||
CAIRO_OPERATOR_SOFT_LIGHT = 22,
|
||||
CAIRO_OPERATOR_DIFFERENCE = 23,
|
||||
CAIRO_OPERATOR_EXCLUSION = 24,
|
||||
CAIRO_OPERATOR_HSL_HUE = 25,
|
||||
CAIRO_OPERATOR_HSL_SATURATION = 26,
|
||||
CAIRO_OPERATOR_HSL_COLOR = 27,
|
||||
CAIRO_OPERATOR_HSL_LUMINOSITY = 28,
|
||||
}
|
||||
|
||||
cenum! {
|
||||
PangoEllipsizeMode, PANGO_ELLIPSIZE_MODES;
|
||||
|
||||
PANGO_ELLIPSIZE_NONE = 0,
|
||||
PANGO_ELLIPSIZE_START = 1,
|
||||
PANGO_ELLIPSIZE_MIDDLE = 2,
|
||||
PANGO_ELLIPSIZE_END = 3,
|
||||
}
|
||||
|
||||
pub const PANGO_SCALE: i32 = 1024;
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
pub const fn format(bpp: u32, ty: u32, a: u32, r: u32, g: u32, b: u32) -> u32 {
|
||||
(bpp << 24) | (ty << 16) | (a << 12) | (r << 8) | (g << 4) | b
|
||||
pub const fn format(bpp: u32, ty: u32, a: u32, r: u32, g: u32, b: u32) -> i32 {
|
||||
((bpp << 24) | (ty << 16) | (a << 12) | (r << 8) | (g << 4) | b) as i32
|
||||
}
|
||||
|
||||
pub const fn format_byte(bpp: u32, ty: u32, a: u32, r: u32, g: u32, b: u32) -> u32 {
|
||||
((bpp >> 3) << 24)
|
||||
pub const fn format_byte(bpp: u32, ty: u32, a: u32, r: u32, g: u32, b: u32) -> i32 {
|
||||
(((bpp >> 3) << 24)
|
||||
| (3 << 22)
|
||||
| (ty << 16)
|
||||
| ((a >> 3) << 12)
|
||||
| ((r >> 3) << 8)
|
||||
| ((g >> 3) << 4)
|
||||
| (b >> 3)
|
||||
| (b >> 3)) as i32
|
||||
}
|
||||
|
||||
pub const fn format_reshift(val: u32, ofs: u32, num: u32) -> u32 {
|
||||
|
|
|
|||
62
src/text.rs
62
src/text.rs
|
|
@ -2,27 +2,25 @@ use crate::format::ARGB8888;
|
|||
use crate::render::{RenderContext, Texture};
|
||||
use crate::theme::Color;
|
||||
use crate::RenderError;
|
||||
use cairo::{ImageSurface, Operator};
|
||||
use pango::{EllipsizeMode, Layout};
|
||||
use pangocairo::cairo::Format;
|
||||
use pangocairo::pango::FontDescription;
|
||||
use pangocairo::{cairo, pango};
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::pango::{CairoImageSurface, PangoError, PangoFontDescription};
|
||||
use crate::pango::consts::{CAIRO_FORMAT_ARGB32, CAIRO_OPERATOR_SOURCE, PANGO_ELLIPSIZE_END, PANGO_SCALE};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum TextError {
|
||||
#[error("Could not create a cairo image")]
|
||||
CreateImage(#[source] cairo::Error),
|
||||
CreateImage(#[source] PangoError),
|
||||
#[error("Could not create a cairo context")]
|
||||
CairoContext(#[source] cairo::Error),
|
||||
CairoContext(#[source] PangoError),
|
||||
#[error("Could not create a pango context")]
|
||||
PangoContext,
|
||||
PangoContext(#[source] PangoError),
|
||||
#[error("Could not create a pango layout")]
|
||||
CreateLayout(#[source] PangoError),
|
||||
#[error("Could not import the rendered text")]
|
||||
RenderError(#[source] RenderError),
|
||||
#[error("Could not access the cairo image data")]
|
||||
ImageData,
|
||||
ImageData(#[source] PangoError),
|
||||
}
|
||||
|
||||
pub fn render(
|
||||
|
|
@ -33,37 +31,39 @@ pub fn render(
|
|||
text: &str,
|
||||
color: Color,
|
||||
) -> Result<Rc<Texture>, TextError> {
|
||||
let image = match ImageSurface::create(Format::ARgb32, width, height) {
|
||||
let image = match CairoImageSurface::new_image_surface(CAIRO_FORMAT_ARGB32, width, height) {
|
||||
Ok(s) => s,
|
||||
Err(e) => return Err(TextError::CreateImage(e)),
|
||||
};
|
||||
let cctx = match cairo::Context::new(&image) {
|
||||
let cctx = match image.create_context() {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Err(TextError::CairoContext(e)),
|
||||
};
|
||||
let pctx = match pangocairo::create_context(&cctx) {
|
||||
Some(c) => c,
|
||||
_ => return Err(TextError::PangoContext),
|
||||
let pctx = match cctx.create_pango_context() {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Err(TextError::PangoContext(e)),
|
||||
};
|
||||
let fd = FontDescription::from_string(font);
|
||||
let layout = Layout::new(&pctx);
|
||||
layout.set_width((width - 2).max(0) * pango::SCALE);
|
||||
layout.set_ellipsize(EllipsizeMode::End);
|
||||
layout.set_font_description(Some(&fd));
|
||||
let fd = PangoFontDescription::from_string(font);
|
||||
let layout = match pctx.create_layout() {
|
||||
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(Operator::Source);
|
||||
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);
|
||||
pangocairo::show_layout(&cctx, &layout);
|
||||
let mut texture = None;
|
||||
let _ = image.with_data(|d| unsafe {
|
||||
let d = mem::transmute(d);
|
||||
texture = Some(ctx.shmem_texture(d, ARGB8888, width, height, image.stride()));
|
||||
});
|
||||
match texture {
|
||||
Some(Ok(t)) => Ok(t),
|
||||
Some(Err(e)) => Err(TextError::RenderError(e)),
|
||||
None => Err(TextError::ImageData),
|
||||
layout.show_layout();
|
||||
image.flush();
|
||||
let data = match image.data() {
|
||||
Ok(d) => d,
|
||||
Err(e) => return Err(TextError::ImageData(e)),
|
||||
};
|
||||
match ctx.shmem_texture(data, ARGB8888, width, height, image.stride()) {
|
||||
Ok(t) => Ok(t),
|
||||
Err(e) => Err(TextError::RenderError(e)),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue