Skip to content

Commit

Permalink
feat: support customizable alignment for image display
Browse files Browse the repository at this point in the history
  • Loading branch information
gaesa committed Dec 6, 2024
1 parent fbf9b3d commit 2a54572
Show file tree
Hide file tree
Showing 15 changed files with 262 additions and 192 deletions.
16 changes: 8 additions & 8 deletions yazi-adapter/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ratatui::layout::Rect;
use tracing::warn;
use yazi_shared::env_exists;

use crate::{Brand, Emulator, SHOWN, TMUX, WSL, drivers};
use crate::{Brand, Emulator, Offset, SHOWN, TMUX, WSL, drivers};

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Adapter {
Expand Down Expand Up @@ -35,18 +35,18 @@ impl Display for Adapter {
}

impl Adapter {
pub async fn image_show(self, path: &Path, max: Rect) -> Result<Rect> {
pub async fn image_show(self, path: &Path, max: Rect, offset: Option<Offset>) -> Result<Rect> {
if max.is_empty() {
return Ok(Rect::default());
}

match self {
Self::Kgp => drivers::Kgp::image_show(path, max).await,
Self::KgpOld => drivers::KgpOld::image_show(path, max).await,
Self::Iip => drivers::Iip::image_show(path, max).await,
Self::Sixel => drivers::Sixel::image_show(path, max).await,
Self::X11 | Self::Wayland => drivers::Ueberzug::image_show(path, max).await,
Self::Chafa => drivers::Chafa::image_show(path, max).await,
Self::Kgp => drivers::Kgp::image_show(path, max, offset).await,
Self::KgpOld => drivers::KgpOld::image_show(path, max, offset).await,
Self::Iip => drivers::Iip::image_show(path, max, offset).await,
Self::Sixel => drivers::Sixel::image_show(path, max, offset).await,
Self::X11 | Self::Wayland => drivers::Ueberzug::image_show(path, max, offset).await,
Self::Chafa => drivers::Chafa::image_show(path, max, offset).await,
}
}

Expand Down
18 changes: 10 additions & 8 deletions yazi-adapter/src/drivers/chafa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ use std::{io::Write, path::Path, process::Stdio};
use ansi_to_tui::IntoText;
use anyhow::{Result, bail};
use crossterm::{cursor::MoveTo, queue};
use ratatui::layout::Rect;
use ratatui::layout::{Rect, Size};
use tokio::process::Command;

use crate::{Adapter, Emulator};
use crate::{Adapter, Emulator, Offset};

pub(crate) struct Chafa;

impl Chafa {
pub(crate) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
pub(crate) async fn image_show(path: &Path, max: Rect, offset: Option<Offset>) -> Result<Rect> {
let output = Command::new("chafa")
.args([
"-f",
Expand Down Expand Up @@ -46,11 +46,13 @@ impl Chafa {
bail!("failed to parse chafa output");
};

let area = Rect {
x: max.x,
y: max.y,
width: first.width() as u16,
height: lines.len() as u16,
let area = {
let width = first.width() as u16;
let height = lines.len() as u16;
let offset = offset.unwrap_or_else(|| {
Offset::from((Size { width, height }, Size { width: max.width, height: max.height }))
});
Rect { x: max.x + offset.x, y: max.y + offset.y, width, height }
};

Adapter::Chafa.image_hide()?;
Expand Down
6 changes: 3 additions & 3 deletions yazi-adapter/src/drivers/iip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use image::{DynamicImage, ExtendedColorType, ImageEncoder, codecs::{jpeg::JpegEn
use ratatui::layout::Rect;
use yazi_config::PREVIEW;

use crate::{CLOSE, Emulator, Image, START, adapter::Adapter};
use crate::{CLOSE, Emulator, Image, Offset, START, adapter::Adapter};

pub(crate) struct Iip;

impl Iip {
pub(crate) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
pub(crate) async fn image_show(path: &Path, max: Rect, offset: Option<Offset>) -> Result<Rect> {
let img = Image::downscale(path, max).await?;
let area = Image::pixel_area((img.width(), img.height()), max);
let area = Image::pixel_area((img.width(), img.height()), max, offset);
let b = Self::encode(img).await?;

Adapter::Iip.image_hide()?;
Expand Down
6 changes: 3 additions & 3 deletions yazi-adapter/src/drivers/kgp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crossterm::{cursor::MoveTo, queue};
use image::DynamicImage;
use ratatui::layout::Rect;

use crate::{CLOSE, ESCAPE, Emulator, START, adapter::Adapter, image::Image};
use crate::{CLOSE, ESCAPE, Emulator, Offset, START, adapter::Adapter, image::Image};

static DIACRITICS: [char; 297] = [
'\u{0305}',
Expand Down Expand Up @@ -312,9 +312,9 @@ static DIACRITICS: [char; 297] = [
pub(crate) struct Kgp;

impl Kgp {
pub(crate) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
pub(crate) async fn image_show(path: &Path, max: Rect, offset: Option<Offset>) -> Result<Rect> {
let img = Image::downscale(path, max).await?;
let area = Image::pixel_area((img.width(), img.height()), max);
let area = Image::pixel_area((img.width(), img.height()), max, offset);

let b1 = Self::encode(img).await?;
let b2 = Self::place(&area)?;
Expand Down
6 changes: 3 additions & 3 deletions yazi-adapter/src/drivers/kgp_old.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ use base64::{Engine, engine::general_purpose};
use image::DynamicImage;
use ratatui::layout::Rect;

use crate::{CLOSE, ESCAPE, Emulator, Image, START, adapter::Adapter};
use crate::{CLOSE, ESCAPE, Emulator, Image, Offset, START, adapter::Adapter};

pub(crate) struct KgpOld;

impl KgpOld {
pub(crate) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
pub(crate) async fn image_show(path: &Path, max: Rect, offset: Option<Offset>) -> Result<Rect> {
let img = Image::downscale(path, max).await?;
let area = Image::pixel_area((img.width(), img.height()), max);
let area = Image::pixel_area((img.width(), img.height()), max, offset);
let b = Self::encode(img).await?;

Adapter::KgpOld.image_hide()?;
Expand Down
6 changes: 3 additions & 3 deletions yazi-adapter/src/drivers/sixel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use image::DynamicImage;
use ratatui::layout::Rect;
use yazi_config::PREVIEW;

use crate::{CLOSE, ESCAPE, Emulator, Image, START, adapter::Adapter};
use crate::{CLOSE, ESCAPE, Emulator, Image, Offset, START, adapter::Adapter};

pub(crate) struct Sixel;

impl Sixel {
pub(crate) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
pub(crate) async fn image_show(path: &Path, max: Rect, offset: Option<Offset>) -> Result<Rect> {
let img = Image::downscale(path, max).await?;
let area = Image::pixel_area((img.width(), img.height()), max);
let area = Image::pixel_area((img.width(), img.height()), max, offset);
let b = Self::encode(img).await?;

Adapter::Sixel.image_hide()?;
Expand Down
18 changes: 10 additions & 8 deletions yazi-adapter/src/drivers/ueberzug.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::{path::{Path, PathBuf}, process::Stdio};

use anyhow::{Result, bail};
use ratatui::layout::Rect;
use ratatui::layout::{Rect, Size};
use tokio::{io::AsyncWriteExt, process::{Child, Command}, sync::mpsc::{self, UnboundedSender}};
use tracing::{debug, warn};
use yazi_config::PREVIEW;
use yazi_shared::{RoCell, env_exists};

use crate::{Adapter, Dimension};
use crate::{Adapter, Dimension, Offset};

type Cmd = Option<(PathBuf, Rect)>;

Expand Down Expand Up @@ -41,7 +41,7 @@ impl Ueberzug {
DEMON.init(Some(tx))
}

pub(crate) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
pub(crate) async fn image_show(path: &Path, max: Rect, offset: Option<Offset>) -> Result<Rect> {
let Some(tx) = &*DEMON else {
bail!("uninitialized ueberzugpp");
};
Expand All @@ -50,11 +50,13 @@ impl Ueberzug {
let (w, h) = tokio::task::spawn_blocking(move || image::image_dimensions(p)).await??;

let area = Dimension::ratio()
.map(|(r1, r2)| Rect {
x: max.x,
y: max.y,
width: max.width.min((w.min(PREVIEW.max_width as _) as f64 / r1).ceil() as _),
height: max.height.min((h.min(PREVIEW.max_height as _) as f64 / r2).ceil() as _),
.map(|(r1, r2)| {
let width = max.width.min((w.min(PREVIEW.max_width as _) as f64 / r1).ceil() as _);
let height = max.height.min((h.min(PREVIEW.max_height as _) as f64 / r2).ceil() as _);
let offset = offset.unwrap_or_else(|| {
Offset::from((Size { width, height }, Size { width: max.width, height: max.height }))
});
Rect { x: max.x + offset.x, y: max.y + offset.y, width, height }
})
.unwrap_or(max);

Expand Down
18 changes: 10 additions & 8 deletions yazi-adapter/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use std::path::{Path, PathBuf};

use anyhow::Result;
use image::{DynamicImage, ExtendedColorType, ImageDecoder, ImageEncoder, ImageError, ImageReader, ImageResult, Limits, codecs::{jpeg::JpegEncoder, png::PngEncoder}, imageops::FilterType, metadata::Orientation};
use ratatui::layout::Rect;
use ratatui::layout::{Rect, Size};
use yazi_config::{PREVIEW, TASKS};

use crate::Dimension;
use crate::{Dimension, Offset};

pub struct Image;

Expand Down Expand Up @@ -73,13 +73,15 @@ impl Image {
.unwrap_or((PREVIEW.max_width, PREVIEW.max_height))
}

pub(super) fn pixel_area(size: (u32, u32), rect: Rect) -> Rect {
pub(super) fn pixel_area(size: (u32, u32), rect: Rect, offset: Option<Offset>) -> Rect {
Dimension::ratio()
.map(|(r1, r2)| Rect {
x: rect.x,
y: rect.y,
width: (size.0 as f64 / r1).ceil() as u16,
height: (size.1 as f64 / r2).ceil() as u16,
.map(|(r1, r2)| {
let width = (size.0 as f64 / r1).ceil() as u16;
let height = (size.1 as f64 / r2).ceil() as u16;
let offset = offset.unwrap_or_else(|| {
Offset::from((Size { width, height }, Size { width: rect.width, height: rect.height }))
});
Rect { x: rect.x + offset.x, y: rect.y + offset.y, width, height }
})
.unwrap_or(rect)
}
Expand Down
2 changes: 1 addition & 1 deletion yazi-adapter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

yazi_macro::mod_pub!(drivers);

yazi_macro::mod_flat!(adapter brand dimension emulator image info mux unknown);
yazi_macro::mod_flat!(adapter brand dimension emulator image info mux offset unknown);

use yazi_shared::{RoCell, SyncCell, env_exists, in_wsl};

Expand Down
26 changes: 26 additions & 0 deletions yazi-adapter/src/offset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use ratatui::layout::Size;
use yazi_config::{PREVIEW, preview::{HorizontalAlignment, VerticalAlignment}};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Offset {
pub x: u16,
pub y: u16,
}

impl From<(Size, Size)> for Offset {
fn from(value: (Size, Size)) -> Self {
let inner = value.0;
let outer = value.1;
let offset_x = match PREVIEW.alignment.horizontal {
HorizontalAlignment::Left => 0,
HorizontalAlignment::Center => (outer.width - inner.width) / 2,
HorizontalAlignment::Right => outer.width - inner.width,
};
let offset_y = match PREVIEW.alignment.vertical {
VerticalAlignment::Top => 0,
VerticalAlignment::Center => (outer.height - inner.height) / 2,
VerticalAlignment::Bottom => outer.height - inner.height,
};
Self { x: offset_x, y: offset_y }
}
}
Loading

0 comments on commit 2a54572

Please sign in to comment.