Skip to content

Commit

Permalink
Merge pull request #256 from swsnr/fix-svg-rendering
Browse files Browse the repository at this point in the history
Fix SVG rendering
  • Loading branch information
swsnr committed Apr 19, 2023
2 parents b544be7 + 72bd38c commit d3bce6b
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 5 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ Use `cargo release` to create a new release.

- Update dependencies.

### Fixed

- Fix SVG rendering:
- Correctly enable SVG rendering and image processing features by default in `mdcat` (see [GH-256]).
- Ignore `charset` and other mime type parameters when checking for `image/svg+xml` (see [GH-256]).

[GH-256]: https://github.com/swsnr/mdcat/pull/256

## [2.0.1] – 2023-04-16

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ system_proxy = { version = "0.3.2", default-features = false }
# Our own crates; pinned to an exact version because we release all of this repo
# in a single version. cargo release takes care of updating these.
mdcat-http-reqwest = { version = "=2.0.1", path = "mdcat-http-reqwest", default-features = false}
pulldown-cmark-mdcat = { version = "=2.0.1", path = "pulldown-cmark-mdcat", default-features = false }
pulldown-cmark-mdcat = { version = "=2.0.1", path = "pulldown-cmark-mdcat" }

[dev-dependencies]
pretty_assertions = "1.3.0"
Expand Down
3 changes: 2 additions & 1 deletion mdcat-http-reqwest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,10 @@ impl HttpResourceHandler {
}

impl ResourceUrlHandler for HttpResourceHandler {
#[instrument(level = "debug", skip(self))]
#[instrument(level = "debug", skip(self), fields(url = %url))]
fn read_resource(&self, url: &Url) -> Result<MimeData> {
filter_schemes(&["http", "https"], url).and_then(|url| {
event!(Level::DEBUG, "Requesting remote HTTP resource {}", url);
let response = self
.http_client
.get(url.clone())
Expand Down
9 changes: 9 additions & 0 deletions pulldown-cmark-mdcat/src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ pub struct MimeData {
pub data: Vec<u8>,
}

impl MimeData {
/// Get the essence of the mime type, if any.
///
/// The essence is roughly the mime type without parameters.
pub fn mime_type_essence(&self) -> Option<&str> {
self.mime_type.as_ref().map(|m| m.essence_str())
}
}

/// Handle resource URLs.
pub trait ResourceUrlHandler: Send + Sync + Debug {
/// Read a resource.
Expand Down
5 changes: 5 additions & 0 deletions pulldown-cmark-mdcat/src/resources/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ impl ResourceUrlHandler for FileResourceHandler {
filter_schemes(&["file"], url).and_then(|url| {
match url.to_file_path() {
Ok(path) => {
event!(
Level::DEBUG,
"Reading from resource file {}",
path.display()
);
let mut buffer = Vec::new();
File::open(&path)?
// Read a byte more than the limit differentiate an expected EOF from hitting the limit
Expand Down
11 changes: 10 additions & 1 deletion pulldown-cmark-mdcat/src/terminal/capabilities/iterm2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::io::{self, Result, Write};

use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use tracing::{event, instrument, Level};

use crate::resources::{svg, InlineImageProtocol};
use crate::terminal::osc::write_osc;
Expand All @@ -39,6 +40,7 @@ impl ITerm2 {
/// supported by macOS, this may yield false positives, i.e. this implementation might not return
/// an error even though iTerm2 cannot actually display the image.
impl InlineImageProtocol for ITerm2 {
#[instrument(skip(self, writer, _terminal_size), fields(url = %url))]
fn write_inline_image(
&self,
writer: &mut dyn Write,
Expand All @@ -47,9 +49,16 @@ impl InlineImageProtocol for ITerm2 {
_terminal_size: &crate::TerminalSize,
) -> Result<()> {
let mime_data = resource_handler.read_resource(url)?;
let contents = if mime_data.mime_type == Some(mime::IMAGE_SVG) {
event!(
Level::DEBUG,
"Received data of mime type {:?}",
mime_data.mime_type
);
let contents = if let Some("image/svg+xml") = mime_data.mime_type_essence() {
event!(Level::DEBUG, "Rendering SVG from {}", url);
Cow::Owned(svg::render_svg_to_png(&mime_data.data)?)
} else {
event!(Level::DEBUG, "Rendering mime data literally");
Cow::Borrowed(&mime_data.data)
};
// Determine the local file name to use, by taking the last segment of the URL.
Expand Down
11 changes: 9 additions & 2 deletions pulldown-cmark-mdcat/src/terminal/capabilities/kitty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use std::str;
use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use thiserror::Error;
use tracing::{event, Level};
use tracing::{event, instrument, Level};

use crate::resources::{InlineImageProtocol, MimeData};
use crate::terminal::size::PixelSize;
Expand Down Expand Up @@ -128,7 +128,8 @@ impl KittyImages {
terminal_size: PixelSize,
) -> Result<KittyImage, KittyImageError> {
use image::{GenericImageView, ImageFormat};
let image = if mime_data.mime_type == Some(mime::IMAGE_SVG) {
let image = if let Some("image/svg+xml") = mime_data.mime_type_essence() {
event!(Level::DEBUG, "Rendering mime data to SVG");
let png_data = crate::resources::svg::render_svg_to_png(&mime_data.data)?;
image::load_from_memory_with_format(&png_data, ImageFormat::Png)?
} else {
Expand Down Expand Up @@ -288,6 +289,7 @@ impl KittyImages {
/// See <https://sw.kovidgoyal.net/kitty/graphics-protocol.html#control-data-reference>
/// for reference.
impl InlineImageProtocol for KittyImages {
#[instrument(skip(self, writer, terminal_size))]
fn write_inline_image(
&self,
writer: &mut dyn Write,
Expand All @@ -302,6 +304,11 @@ impl InlineImageProtocol for KittyImages {
)
})?;
let mime_data = resource_handler.read_resource(url)?;
event!(
Level::DEBUG,
"Received data of mime type {:?}",
mime_data.mime_type
);
let image = self.render(mime_data, pixel_size)?;
image.write_to(writer)
}
Expand Down

0 comments on commit d3bce6b

Please sign in to comment.