2024-01-01 22:41:56 +01:00
|
|
|
// Copyright (c) 2023-2024 Sophie Herold
|
2023-11-29 21:15:36 +01:00
|
|
|
// Copyright (c) 2023 Julian Hofer
|
2023-04-19 20:02:01 +02:00
|
|
|
//
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
//
|
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
|
2023-05-23 01:49:40 +02:00
|
|
|
//! Decodes several image formats
|
2023-12-26 22:07:46 +01:00
|
|
|
|
2023-04-17 22:38:52 +02:00
|
|
|
pub mod formats;
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
pub mod tiling;
|
|
|
|
|
|
2023-12-06 23:45:02 +01:00
|
|
|
use std::sync::Arc;
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
|
2023-05-23 01:49:40 +02:00
|
|
|
use anyhow::Result;
|
2024-09-27 02:40:21 +02:00
|
|
|
use async_channel as mpsc;
|
2024-01-01 22:41:56 +01:00
|
|
|
pub use formats::RSVG_MAX_SIZE;
|
2023-12-06 23:45:02 +01:00
|
|
|
use formats::*;
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
|
2023-12-26 22:07:46 +01:00
|
|
|
use self::tiling::SharedFrameBuffer;
|
2023-12-06 23:45:02 +01:00
|
|
|
use crate::deps::*;
|
2024-01-01 22:41:56 +01:00
|
|
|
use crate::metadata::Metadata;
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
|
/// Renderer requests new tiles
|
|
|
|
|
///
|
|
|
|
|
/// This happens for initial loading or when zoom level or viewing area changes.
|
|
|
|
|
pub struct TileRequest {
|
|
|
|
|
pub viewport: graphene::Rect,
|
2023-04-16 01:36:38 +02:00
|
|
|
pub area: graphene::Rect,
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
pub zoom: f64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
/// Signals update to the renderer
|
|
|
|
|
pub struct UpdateSender {
|
2024-09-27 02:40:21 +02:00
|
|
|
sender: mpsc::Sender<DecoderUpdate>,
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2023-03-14 00:10:14 +01:00
|
|
|
/// Signals for renderer (LpImage)
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
pub enum DecoderUpdate {
|
|
|
|
|
/// Dimensions of image in `TilingSore` available/updated
|
2024-01-01 22:41:56 +01:00
|
|
|
Dimensions,
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
/// Metadata available
|
2024-01-01 22:41:56 +01:00
|
|
|
Metadata(Box<Metadata>),
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
/// New image data available, redraw
|
|
|
|
|
Redraw,
|
2023-05-23 01:49:40 +02:00
|
|
|
/// Start animation
|
|
|
|
|
Animated,
|
2024-07-19 23:19:34 +02:00
|
|
|
SpecificError(DecoderError),
|
2023-11-30 21:58:26 +01:00
|
|
|
/// And error occurred during decoding
|
2024-07-19 23:19:34 +02:00
|
|
|
GenericError(anyhow::Error),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(glib::Enum, Debug, Clone, Copy, Default, PartialEq, Eq)]
|
|
|
|
|
#[enum_type(name = "LpDecoderError")]
|
|
|
|
|
//#[enum_dynamic(lazy_registration = true)]
|
|
|
|
|
#[repr(i32)]
|
|
|
|
|
pub enum DecoderError {
|
|
|
|
|
/// Image format not supported or unknown
|
|
|
|
|
UnsupportedFormat,
|
|
|
|
|
/// No glycin-loaders installed
|
|
|
|
|
NoLoadersConfigured,
|
2024-07-26 22:54:24 +02:00
|
|
|
/// Memory limit exceeded
|
|
|
|
|
OutOfMemory,
|
2024-07-19 23:19:34 +02:00
|
|
|
#[default]
|
|
|
|
|
None,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl DecoderError {
|
|
|
|
|
pub fn is_err(self) -> bool {
|
|
|
|
|
matches!(self, Self::None)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_ok(self) -> bool {
|
|
|
|
|
!matches!(self, Self::None)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl glib::value::ToValueOptional for DecoderError {
|
|
|
|
|
fn to_value_optional(s: Option<&Self>) -> glib::Value {
|
|
|
|
|
s.unwrap_or(&Self::None).into()
|
|
|
|
|
}
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl UpdateSender {
|
|
|
|
|
pub fn send(&self, update: DecoderUpdate) {
|
2024-09-27 02:40:21 +02:00
|
|
|
let result = self.sender.force_send(update);
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
|
2024-09-27 02:40:21 +02:00
|
|
|
match result {
|
|
|
|
|
Err(err) => log::error!("Failed to send update: {err}"),
|
|
|
|
|
Ok(Some(msg)) => log::error!("Unexpectedly replaced the message {msg:?}"),
|
|
|
|
|
_ => {}
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-30 21:58:26 +01:00
|
|
|
/// Send occurring errors to renderer
|
2023-08-04 13:20:41 +02:00
|
|
|
pub fn spawn_error_handled<F>(&self, f: F) -> glib::JoinHandle<()>
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
where
|
2024-07-18 01:51:51 +02:00
|
|
|
F: std::future::Future<Output = Result<(), glycin::ErrorCtx>> + Send + 'static,
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
{
|
|
|
|
|
let update_sender = self.clone();
|
2023-11-22 09:12:07 +01:00
|
|
|
glib::spawn_future(async move {
|
2023-08-04 13:20:41 +02:00
|
|
|
let update_sender = update_sender.clone();
|
|
|
|
|
|
2024-07-18 01:51:51 +02:00
|
|
|
let result: Result<(), glycin::ErrorCtx> = f.await;
|
2023-08-04 13:20:41 +02:00
|
|
|
|
|
|
|
|
if let Err(err) = result {
|
2024-07-29 03:32:13 +02:00
|
|
|
update_sender.send_error(err);
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
2024-07-29 03:32:13 +02:00
|
|
|
|
|
|
|
|
pub fn send_error(&self, err: glycin::ErrorCtx) {
|
2025-12-03 22:35:13 +01:00
|
|
|
if let Some(mime_type) = err.unsupported_format() {
|
|
|
|
|
let mut metadata = Metadata::default();
|
|
|
|
|
metadata.set_mime_type(mime_type);
|
|
|
|
|
|
|
|
|
|
self.send(DecoderUpdate::Metadata(Box::new(metadata)));
|
2024-07-29 03:32:13 +02:00
|
|
|
self.send(DecoderUpdate::SpecificError(
|
|
|
|
|
DecoderError::UnsupportedFormat,
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
if err.is_out_of_memory() {
|
|
|
|
|
self.send(DecoderUpdate::SpecificError(DecoderError::OutOfMemory));
|
|
|
|
|
} else if matches!(err.error(), glycin::Error::NoLoadersConfigured(_)) {
|
|
|
|
|
self.send(DecoderUpdate::SpecificError(
|
|
|
|
|
DecoderError::NoLoadersConfigured,
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
self.send(DecoderUpdate::GenericError(err.into()));
|
|
|
|
|
}
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct Decoder {
|
|
|
|
|
decoder: FormatDecoder,
|
2023-04-10 17:53:15 +02:00
|
|
|
update_sender: UpdateSender,
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
enum FormatDecoder {
|
2023-05-23 01:49:40 +02:00
|
|
|
Glycin(Glycin),
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
Svg(Svg),
|
2025-12-03 22:35:13 +01:00
|
|
|
Failed,
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Decoder {
|
|
|
|
|
/// Get new image decoder
|
|
|
|
|
///
|
2023-03-15 22:35:59 +01:00
|
|
|
/// The textures will be stored in the passed `TiledImage`.
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
/// The renderer should listen to updates from the returned receiver.
|
2023-03-14 00:10:14 +01:00
|
|
|
pub async fn new(
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
file: gio::File,
|
2023-12-26 22:07:46 +01:00
|
|
|
tiles: Arc<SharedFrameBuffer>,
|
2024-09-27 02:40:21 +02:00
|
|
|
) -> (Self, mpsc::Receiver<DecoderUpdate>) {
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
let (sender, receiver) = mpsc::unbounded();
|
|
|
|
|
|
|
|
|
|
let update_sender = UpdateSender { sender };
|
|
|
|
|
tiles.set_update_sender(update_sender.clone());
|
|
|
|
|
|
2025-12-03 22:35:13 +01:00
|
|
|
log::trace!("Setting up loader");
|
|
|
|
|
let mut loader = glycin::Loader::new(file);
|
|
|
|
|
loader.apply_transformations(false);
|
|
|
|
|
|
|
|
|
|
let image = match loader.load().await {
|
|
|
|
|
Ok(image) => image,
|
|
|
|
|
Err(err) => {
|
|
|
|
|
update_sender.send_error(err);
|
|
|
|
|
return (
|
|
|
|
|
Self {
|
|
|
|
|
decoder: FormatDecoder::Failed,
|
|
|
|
|
update_sender,
|
|
|
|
|
},
|
|
|
|
|
receiver,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let format_decoder = Self::format_decoder(update_sender.clone(), image, tiles);
|
|
|
|
|
|
2023-05-23 01:49:40 +02:00
|
|
|
let decoder = Self {
|
|
|
|
|
decoder: format_decoder,
|
|
|
|
|
update_sender,
|
2023-04-28 00:44:04 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
(decoder, receiver)
|
2023-03-14 00:10:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn format_decoder(
|
|
|
|
|
update_sender: UpdateSender,
|
2025-12-03 22:35:13 +01:00
|
|
|
image: glycin::Image,
|
2023-12-26 22:07:46 +01:00
|
|
|
tiles: Arc<SharedFrameBuffer>,
|
2023-05-23 01:49:40 +02:00
|
|
|
) -> FormatDecoder {
|
2025-12-03 22:35:13 +01:00
|
|
|
let mime_type = image.mime_type().to_string();
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
|
2025-12-03 22:35:13 +01:00
|
|
|
// Known things we want to match here are
|
|
|
|
|
// - image/svg+xml
|
|
|
|
|
// - image/svg+xml-compressed
|
|
|
|
|
if mime_type.split('+').next() == Some("image/svg") {
|
|
|
|
|
return FormatDecoder::Svg(Svg::new(image, update_sender, tiles));
|
|
|
|
|
} else {
|
|
|
|
|
FormatDecoder::Glycin(Glycin::new(image, update_sender, tiles))
|
|
|
|
|
}
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Request missing tiles
|
|
|
|
|
pub fn request(&self, tile_request: TileRequest) {
|
2023-05-23 01:49:40 +02:00
|
|
|
if let FormatDecoder::Svg(svg) = &self.decoder {
|
|
|
|
|
if let Err(err) = svg.request(tile_request) {
|
2024-07-19 23:19:34 +02:00
|
|
|
self.update_sender.send(DecoderUpdate::GenericError(err));
|
2023-04-10 17:53:15 +02:00
|
|
|
}
|
2023-05-23 01:49:40 +02:00
|
|
|
}
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
}
|
2023-03-15 22:35:59 +01:00
|
|
|
|
|
|
|
|
pub fn fill_frame_buffer(&self) {
|
2023-05-23 01:49:40 +02:00
|
|
|
if let FormatDecoder::Glycin(decoder) = &self.decoder {
|
2023-03-15 22:35:59 +01:00
|
|
|
decoder.fill_frame_buffer();
|
|
|
|
|
} else {
|
|
|
|
|
log::error!("Trying to fill frame buffer for decoder without animation support");
|
|
|
|
|
}
|
|
|
|
|
}
|
decoder: Use image-rs, libheif-rs, librsvg
This adds proper support for a lot of image formats including SVGs.
It will be the basis for many features to come. The technical core
is an asynchronous renderer that can arrange textures in smaller tiles
which might be generated on demand.
Closes #34, #40, #41, #49
Basis for fixing the following issues #7, #27, #36, #43, #68, #71
2023-03-04 03:14:52 +01:00
|
|
|
}
|