2023-04-19 20:02:01 +02:00
|
|
|
// Copyright (c) 2023 Sophie Herold
|
|
|
|
|
//
|
|
|
|
|
// 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
|
|
|
|
|
|
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
|
|
|
///! Tiled renderer
|
|
|
|
|
///!
|
|
|
|
|
///! It is not always feasible or desiareble to store the complete decoded
|
2023-03-15 22:35:59 +01:00
|
|
|
///! image in the VRAM. [`TiledImage`] allows to compose the parts of
|
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 image currently viewed, out of smaller [`Tiles`].
|
|
|
|
|
///!
|
|
|
|
|
///! This is especially important for SVGs where every the image has to
|
|
|
|
|
///! be re-genearted for each zoom level. It can also be used to allow
|
|
|
|
|
///! showing large JPEGs etc where the complete decoded image would not
|
|
|
|
|
///! even fit in the VRAM.
|
2023-03-10 19:08:26 +01:00
|
|
|
use super::{DecoderUpdate, ImageDimensionDetails, 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
|
|
|
use crate::deps::*;
|
|
|
|
|
|
|
|
|
|
use arc_swap::ArcSwap;
|
|
|
|
|
use gtk::prelude::*;
|
|
|
|
|
|
|
|
|
|
use std::collections::BTreeMap;
|
2023-03-15 22:35:59 +01:00
|
|
|
use std::collections::VecDeque;
|
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
|
|
|
use std::sync::Arc;
|
2023-03-15 22:35:59 +01:00
|
|
|
use std::time::Duration;
|
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-04-16 01:36:38 +02:00
|
|
|
const ZOOM_SIGNIFICANT_DIGITS: i32 = 6;
|
|
|
|
|
pub const MIN_TILE_SIZE: u16 = 500;
|
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 type ZoomLevel = u32;
|
|
|
|
|
pub type Coordinate = u32;
|
|
|
|
|
pub type Coordinates = (u32, u32);
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
/// Part of the image
|
|
|
|
|
pub struct Tile {
|
|
|
|
|
pub position: Coordinates,
|
|
|
|
|
pub zoom_level: ZoomLevel,
|
|
|
|
|
/// Border that gets cut away to avoid scaling artifacts at the sides
|
|
|
|
|
pub bleed: u8,
|
|
|
|
|
pub texture: gdk::Texture,
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-07 00:44:07 +01:00
|
|
|
/// Temporary function until HighDPI is sorted out
|
|
|
|
|
///
|
|
|
|
|
/// TODO: Does this has to follow scaling factor?
|
|
|
|
|
#[must_use]
|
|
|
|
|
pub fn round(r: &graphene::Rect) -> graphene::Rect {
|
|
|
|
|
graphene::Rect::new(
|
|
|
|
|
r.x().round(),
|
|
|
|
|
r.y().round(),
|
|
|
|
|
r.width().round(),
|
|
|
|
|
r.height().round(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
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 Tile {
|
|
|
|
|
pub fn area(&self) -> graphene::Rect {
|
|
|
|
|
let bleed = self.bleed as f32;
|
|
|
|
|
// The texture is rendered slightly larger such that bleed can be cut away
|
|
|
|
|
self.area_with_bleed().inset_r(bleed, bleed)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn area_with_bleed(&self) -> graphene::Rect {
|
|
|
|
|
let width = self.texture.width() as f32;
|
|
|
|
|
let height = self.texture.height() as f32;
|
|
|
|
|
let bleed = self.bleed as f32;
|
|
|
|
|
graphene::Rect::new(
|
|
|
|
|
self.position.0 as f32 - bleed,
|
|
|
|
|
self.position.1 as f32 - bleed,
|
|
|
|
|
width,
|
|
|
|
|
height,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn zoom(&self) -> f32 {
|
|
|
|
|
level_to_zoom(self.zoom_level) as f32
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Add tile to snapshot
|
|
|
|
|
///
|
|
|
|
|
/// This is where parts of images actually land on the screen
|
2023-03-27 06:30:02 +02:00
|
|
|
pub fn add_to_snapshot(
|
|
|
|
|
&self,
|
|
|
|
|
snapshot: >k::Snapshot,
|
|
|
|
|
output_zoom: f64,
|
|
|
|
|
options: &RenderOptions,
|
|
|
|
|
) {
|
|
|
|
|
// Multiply by scale factor to get the image scaled to `zoom` in physical pixels
|
|
|
|
|
let zoom = output_zoom as f32 * options.scale_factor as f32 / self.zoom();
|
|
|
|
|
let area = round(&self.area().scale(zoom, zoom));
|
|
|
|
|
let area_with_bleed = round(&self.area_with_bleed().scale(zoom, zoom));
|
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-04-02 01:39:23 +02:00
|
|
|
if area_with_bleed.width() < 1. || area_with_bleed.height() < 1. {
|
|
|
|
|
log::warn!("Trying to draw image with dimensions smaller than 1");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
// TODO: do not clip outer bounderies of the image
|
|
|
|
|
snapshot.push_clip(&area);
|
2023-04-16 01:36:38 +02:00
|
|
|
// TODO: do not clip outer boundaries of the image
|
2023-04-02 22:22:00 +02:00
|
|
|
if let Some(background_color) = &options.background_color {
|
2023-04-16 01:36:38 +02:00
|
|
|
snapshot.append_color(background_color, &area_with_bleed);
|
2023-04-02 22:22:00 +02:00
|
|
|
}
|
2023-03-07 00:44:07 +01:00
|
|
|
snapshot.append_scaled_texture(&self.texture, options.scaling_filter, &area_with_bleed);
|
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
|
|
|
snapshot.pop();
|
2023-04-16 01:36:38 +02:00
|
|
|
|
|
|
|
|
if std::env::var_os("LOUPE_TILING_DEBUG").map_or(false, |x| x.len() > 0) {
|
|
|
|
|
snapshot.append_inset_shadow(
|
|
|
|
|
&gsk::RoundedRect::from_rect(area, 0.),
|
|
|
|
|
&gdk::RGBA::new(1., 0., 0., 0.7),
|
|
|
|
|
0.,
|
|
|
|
|
0.,
|
|
|
|
|
10.,
|
|
|
|
|
0.,
|
|
|
|
|
);
|
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn coordinates(&self) -> Coordinates {
|
|
|
|
|
self.position
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-15 22:35:59 +01:00
|
|
|
/// Buffers multiple images for animations
|
|
|
|
|
///
|
|
|
|
|
/// If the image is not animated, this only contains one image
|
|
|
|
|
#[derive(Clone, Debug, Default)]
|
|
|
|
|
pub struct FrameBuffer {
|
|
|
|
|
/// The first entry is always the currently shown frame
|
|
|
|
|
pub images: VecDeque<TiledImage>,
|
|
|
|
|
pub update_sender: Option<UpdateSender>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl FrameBuffer {
|
|
|
|
|
/// Returns mutable reference to the current image
|
|
|
|
|
///
|
|
|
|
|
/// This is a convenience functions for the case of non-animated images.
|
|
|
|
|
/// If no image exists yet, a new one is inserted an returned.
|
|
|
|
|
pub fn current(&mut self) -> &mut TiledImage {
|
|
|
|
|
if self.images.is_empty() {
|
|
|
|
|
self.images.push_back(TiledImage::default())
|
|
|
|
|
}
|
|
|
|
|
self.images.front_mut().unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn original_dimensions(&self) -> Option<Coordinates> {
|
|
|
|
|
self.images.front()?.original_dimensions
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_update_sender(&mut self, sender: UpdateSender) {
|
|
|
|
|
self.update_sender = Some(sender);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Render the current image into this snapshot
|
|
|
|
|
pub fn add_to_snapshot(&self, snapshot: >k::Snapshot, zoom: f64, options: &RenderOptions) {
|
|
|
|
|
if let Some(tiling) = self.images.front() {
|
|
|
|
|
tiling.add_to_snapshot(snapshot, zoom, options);
|
|
|
|
|
} else {
|
|
|
|
|
log::error!("Trying to snapshot empty tiling queue");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn cleanup(&mut self, zoom: f64, viewport: graphene::Rect) {
|
|
|
|
|
self.current().cleanup(zoom, viewport);
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-13 01:19:53 +02:00
|
|
|
/// Delete all stored information
|
|
|
|
|
///
|
|
|
|
|
/// Used when reloading image
|
|
|
|
|
pub fn reset(&mut self) {
|
|
|
|
|
self.update_sender = None;
|
|
|
|
|
self.images.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-15 22:35:59 +01:00
|
|
|
pub fn contains(&self, zoom: f64, coordinates: Coordinates) -> bool {
|
|
|
|
|
self.images
|
|
|
|
|
.front()
|
|
|
|
|
.map_or(false, |x| x.contains(zoom, coordinates))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-16 01:36:38 +02:00
|
|
|
#[derive(Clone, Debug, Default)]
|
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
|
|
|
/// Store tiles for image
|
2023-03-15 22:35:59 +01:00
|
|
|
///
|
|
|
|
|
/// This is the common representation for image textures.
|
|
|
|
|
/// I many cases there might only be one tile.
|
|
|
|
|
pub struct TiledImage {
|
2023-04-16 01:36:38 +02:00
|
|
|
pub tile_layers: BTreeMap<ZoomLevel, TileLayer>,
|
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
|
|
|
/// Complete image size
|
|
|
|
|
pub original_dimensions: Option<Coordinates>,
|
2023-03-15 22:35:59 +01:00
|
|
|
/// Delay until to show this frame if animated
|
|
|
|
|
pub delay: std::time::Duration,
|
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-04-16 01:36:38 +02:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct TileLayer {
|
|
|
|
|
tiles: BTreeMap<Coordinates, Tile>,
|
|
|
|
|
covering: Covering,
|
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, Clone)]
|
|
|
|
|
pub struct RenderOptions {
|
|
|
|
|
pub scaling_filter: gsk::ScalingFilter,
|
2023-03-27 06:30:02 +02:00
|
|
|
pub scale_factor: i32,
|
2023-04-02 22:22:00 +02:00
|
|
|
pub background_color: Option<gdk::RGBA>,
|
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
|
|
|
impl 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
|
|
|
/// Render tiles as image
|
|
|
|
|
///
|
|
|
|
|
/// This is what actually draws the image
|
|
|
|
|
pub fn add_to_snapshot(&self, snapshot: >k::Snapshot, zoom: f64, options: &RenderOptions) {
|
|
|
|
|
let tiles: Vec<_> = self
|
2023-04-16 01:36:38 +02:00
|
|
|
.iter_tiles_rendering_priority(zoom)
|
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
|
|
|
.flat_map(|(_, tiles)| tiles)
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
log::trace!("Rendering {} tiles", tiles.len());
|
2023-03-27 06:30:02 +02:00
|
|
|
|
|
|
|
|
// Scale from application pixels back to physical pixels
|
|
|
|
|
snapshot.scale(
|
|
|
|
|
1. / options.scale_factor as f32,
|
|
|
|
|
1. / options.scale_factor as f32,
|
|
|
|
|
);
|
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
|
|
|
// reverse to put least fitting tiles in the background
|
|
|
|
|
for (_, tile) in tiles.iter().rev() {
|
2023-03-07 00:44:07 +01:00
|
|
|
tile.add_to_snapshot(snapshot, zoom, options);
|
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-27 06:30:02 +02:00
|
|
|
// reset scale
|
|
|
|
|
snapshot.scale(options.scale_factor as f32, options.scale_factor as f32);
|
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 fn push(&mut self, tile: Tile) {
|
2023-04-16 01:36:38 +02:00
|
|
|
let layer = self
|
|
|
|
|
.tile_layers
|
|
|
|
|
.entry(tile.zoom_level)
|
|
|
|
|
.or_insert_with(|| TileLayer {
|
|
|
|
|
tiles: Default::default(),
|
|
|
|
|
covering: Covering::Simple,
|
|
|
|
|
});
|
|
|
|
|
layer.tiles.insert(tile.coordinates(), tile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn push_tile(&mut self, tiling: Tiling, position: Coordinates, texture: gdk::Texture) {
|
|
|
|
|
let tile = Tile {
|
|
|
|
|
position,
|
|
|
|
|
texture,
|
|
|
|
|
zoom_level: zoom_to_level(tiling.zoom),
|
|
|
|
|
bleed: tiling.bleed,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let layer = self
|
|
|
|
|
.tile_layers
|
|
|
|
|
.entry(tile.zoom_level)
|
|
|
|
|
.or_insert_with(|| TileLayer {
|
|
|
|
|
tiles: Default::default(),
|
|
|
|
|
covering: Covering::Tiling(tiling),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
layer.tiles.insert(tile.coordinates(), tile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_layer_tiling_or_default(&mut self, zoom: f64, viewport: graphene::Rect) -> Tiling {
|
|
|
|
|
let zoom_level = zoom_to_level(zoom);
|
|
|
|
|
if let Some(TileLayer {
|
|
|
|
|
covering: Covering::Tiling(tiling),
|
|
|
|
|
..
|
|
|
|
|
}) = self.tile_layers.get(&zoom_level)
|
|
|
|
|
{
|
|
|
|
|
return *tiling;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let tiling = Tiling {
|
|
|
|
|
origin: (viewport.x() as u32, viewport.y() as u32),
|
|
|
|
|
tile_width: u16::max(MIN_TILE_SIZE, viewport.width() as u16),
|
|
|
|
|
tile_height: u16::max(MIN_TILE_SIZE, viewport.height() as u16),
|
|
|
|
|
zoom,
|
|
|
|
|
bleed: 0,
|
|
|
|
|
original_dimensions: self.original_dimensions.unwrap_or_default(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
self.tile_layers.insert(
|
|
|
|
|
zoom_level,
|
|
|
|
|
TileLayer {
|
|
|
|
|
tiles: Default::default(),
|
|
|
|
|
covering: Covering::Tiling(tiling),
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
tiling
|
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 fn contains(&self, zoom: f64, coordinates: Coordinates) -> bool {
|
2023-04-16 01:36:38 +02:00
|
|
|
let Some(tile_layer) = self.tile_layers.get(&zoom_to_level(zoom)) else { return false };
|
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-04-16 01:36:38 +02:00
|
|
|
tile_layer.tiles.contains_key(&coordinates)
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Tiles ordered by how good they are suited for the zoom level
|
2023-04-16 01:36:38 +02:00
|
|
|
pub fn iter_tiles_rendering_priority(
|
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
|
|
|
&self,
|
|
|
|
|
zoom: f64,
|
|
|
|
|
) -> impl Iterator<Item = (&ZoomLevel, &BTreeMap<Coordinates, Tile>)> {
|
2023-04-16 01:36:38 +02:00
|
|
|
self.iter_rendering_priority(zoom)
|
|
|
|
|
.map(|(level, layer)| (level, &layer.tiles))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn iter_rendering_priority(
|
|
|
|
|
&self,
|
|
|
|
|
zoom: f64,
|
|
|
|
|
) -> impl Iterator<Item = (&ZoomLevel, &TileLayer)> {
|
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 zoom_level = zoom_to_level(zoom);
|
2023-04-16 01:36:38 +02:00
|
|
|
self.tile_layers
|
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
|
|
|
// Tiles at zoom level and with better resolution
|
|
|
|
|
.range(zoom_level..)
|
|
|
|
|
// Afterwards try tiles with worse resolution
|
2023-04-16 01:36:38 +02:00
|
|
|
.chain(self.tile_layers.range(..zoom_level).rev())
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Viewport within zoom coordinates
|
|
|
|
|
///
|
2023-04-16 01:36:38 +02:00
|
|
|
/// preserve_area: Slightly larger than the viewport, area for which we want 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
|
|
|
/// TODO: This is the most buggy function ever
|
2023-04-16 01:36:38 +02:00
|
|
|
pub fn cleanup(&mut self, zoom: f64, preserve_area: graphene::Rect) {
|
|
|
|
|
let zoom = zoom_normalize(zoom);
|
|
|
|
|
let mut kept_tiles = Self::default();
|
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
|
|
|
|
|
|
|
|
// Always work with 100% zoom level for tiles
|
2023-04-16 01:36:38 +02:00
|
|
|
let preserve_area_100 = preserve_area.scale(1. / zoom as f32, 1. / zoom as f32);
|
|
|
|
|
let mut missing_tiles = vec![preserve_area_100];
|
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-04-16 01:36:38 +02:00
|
|
|
// Keep tiles in total-zoom-out layer
|
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
|
|
|
// TODO: Change the top layer if window size changes
|
2023-04-16 01:36:38 +02:00
|
|
|
if let Some((_, top_layer)) = self.tile_layers.iter().next() {
|
|
|
|
|
for tile in top_layer.tiles.values() {
|
|
|
|
|
if let Covering::Tiling(tiling) = top_layer.covering {
|
|
|
|
|
kept_tiles.push_tile(tiling, tile.position, tile.texture.clone());
|
|
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Put all tiles in correct processing order
|
|
|
|
|
let stored_tiles = self.iter_rendering_priority(zoom);
|
|
|
|
|
|
2023-04-16 01:36:38 +02:00
|
|
|
for (zoom_level, tile_layer) in stored_tiles {
|
|
|
|
|
// This should always be tiled since "Simple" would be in total-zoom-out layer
|
|
|
|
|
if let Covering::Tiling(tiling) = tile_layer.covering {
|
|
|
|
|
let tiles = &tile_layer.tiles;
|
|
|
|
|
let tile_zoom = level_to_zoom(*zoom_level);
|
|
|
|
|
|
|
|
|
|
let mut next_missing_tiles = vec![];
|
|
|
|
|
|
|
|
|
|
// Tiling for this zoom level and viewport
|
|
|
|
|
|
|
|
|
|
let preserve_area_tiling =
|
|
|
|
|
preserve_area_100.scale(tiling.zoom as f32, tiling.zoom as f32);
|
|
|
|
|
for mut tile_instruction in tiling.relevant_tiles(&preserve_area_tiling) {
|
|
|
|
|
// scale to 100% reference
|
|
|
|
|
tile_instruction.area = tile_instruction
|
|
|
|
|
.area
|
|
|
|
|
.scale(1. / tile_zoom as f32, 1. / tile_zoom as f32);
|
|
|
|
|
|
|
|
|
|
// Determine if tile of this zoom level has overlap with a missing tile
|
|
|
|
|
let mut intersections = missing_tiles
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|missing| tile_instruction.area.is_intersected(missing))
|
|
|
|
|
.peekable();
|
|
|
|
|
|
|
|
|
|
if intersections.peek().is_some() {
|
|
|
|
|
if let Some(tile) = tiles.get(&tile_instruction.coordinates) {
|
|
|
|
|
// we have this tile and can provide it
|
|
|
|
|
kept_tiles.push_tile(tiling, tile.position, tile.texture.clone());
|
|
|
|
|
} else {
|
|
|
|
|
for missing in missing_tiles.iter() {
|
|
|
|
|
if let Some(overlap) = missing.intersection(&tile_instruction.area)
|
|
|
|
|
{
|
|
|
|
|
next_missing_tiles.push(overlap);
|
|
|
|
|
}
|
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-04-16 01:36:38 +02:00
|
|
|
missing_tiles = next_missing_tiles;
|
|
|
|
|
} else {
|
|
|
|
|
log::error!("Images should never have multiple 'Simple' layers: {tile_layer:?}");
|
|
|
|
|
}
|
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-04-16 01:36:38 +02:00
|
|
|
log::trace!(
|
|
|
|
|
"Cleanup kept {} tiles",
|
|
|
|
|
kept_tiles
|
|
|
|
|
.tile_layers
|
|
|
|
|
.values()
|
|
|
|
|
.flat_map(|x| x.tiles.iter())
|
|
|
|
|
.count()
|
|
|
|
|
);
|
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-04-16 01:36:38 +02:00
|
|
|
self.tile_layers = kept_tiles.tile_layers;
|
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-04-16 01:36:38 +02:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
|
pub enum Covering {
|
|
|
|
|
Simple,
|
|
|
|
|
Tiling(Tiling),
|
|
|
|
|
}
|
|
|
|
|
|
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, Clone, Copy)]
|
|
|
|
|
/// Abstract definition of a tiling
|
|
|
|
|
pub struct Tiling {
|
2023-04-16 01:36:38 +02:00
|
|
|
pub origin: Coordinates,
|
|
|
|
|
pub tile_width: u16,
|
|
|
|
|
pub tile_height: u16,
|
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 original_dimensions: Coordinates,
|
|
|
|
|
pub zoom: f64,
|
|
|
|
|
pub bleed: u8,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Tiling {
|
|
|
|
|
pub fn scaled_dimensions(&self) -> Coordinates {
|
|
|
|
|
let (w, h) = self.original_dimensions;
|
|
|
|
|
(
|
|
|
|
|
(w as f64 * self.zoom) as Coordinate,
|
|
|
|
|
(h as f64 * self.zoom) as Coordinate,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-16 01:36:38 +02:00
|
|
|
pub fn origin_shift_x(&self) -> f32 {
|
|
|
|
|
let width = self.origin.0 as f32;
|
|
|
|
|
let rem = width.rem_euclid(self.tile_width as f32);
|
|
|
|
|
if rem > 0. {
|
|
|
|
|
rem - self.tile_width as f32
|
|
|
|
|
} else {
|
|
|
|
|
0.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn origin_shift_y(&self) -> f32 {
|
|
|
|
|
let height = self.origin.1 as f32;
|
|
|
|
|
let rem = height.rem_euclid(self.tile_height as f32);
|
|
|
|
|
if rem > 0. {
|
|
|
|
|
rem - self.tile_height as f32
|
|
|
|
|
} else {
|
|
|
|
|
0.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
/// Returns relevant tiles
|
|
|
|
|
///
|
|
|
|
|
/// This gives what tiles are needed for convering the `preload_area`.
|
|
|
|
|
/// Decoders use the [`TileInstructions`] to know what they have to render.
|
|
|
|
|
pub fn relevant_tiles(&self, preload_area: &graphene::Rect) -> Vec<TileInstructions> {
|
2023-04-16 01:36:38 +02:00
|
|
|
let original_width = self.scaled_dimensions().0 as f32;
|
|
|
|
|
let original_height = self.scaled_dimensions().1 as f32;
|
|
|
|
|
|
|
|
|
|
let tile_width = self.tile_width as f32;
|
|
|
|
|
let tile_height = self.tile_height as f32;
|
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-04-16 01:36:38 +02:00
|
|
|
let x0 = (preload_area.x() / tile_width).floor() * tile_width + self.origin_shift_x();
|
|
|
|
|
let x1 = ((preload_area.x() + preload_area.width()) / tile_width).ceil() * tile_width
|
|
|
|
|
+ self.origin_shift_x();
|
|
|
|
|
let y0 = (preload_area.y() / tile_height).floor() * tile_height + self.origin_shift_y();
|
|
|
|
|
let y1 = ((preload_area.y() + preload_area.height()) / tile_height).ceil() * tile_height
|
|
|
|
|
+ self.origin_shift_y();
|
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 mut tiles = Vec::new();
|
2023-04-16 01:36:38 +02:00
|
|
|
for x in (x0 as i32..=x1 as i32).step_by(self.tile_width.into()) {
|
|
|
|
|
for y in (y0 as i32..=y1 as i32).step_by(self.tile_height.into()) {
|
|
|
|
|
let area = graphene::Rect::new(x as f32, y as f32, tile_width, tile_height);
|
|
|
|
|
let Some(restricted_area) = area.restrict(original_width, original_height) else { continue; };
|
|
|
|
|
|
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 tile = TileInstructions {
|
|
|
|
|
tiling: *self,
|
2023-04-16 01:36:38 +02:00
|
|
|
area: restricted_area,
|
|
|
|
|
coordinates: (restricted_area.x() as u32, restricted_area.y() as u32),
|
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
|
|
|
};
|
|
|
|
|
tiles.push(tile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tiles.sort_by_key(|tile| tile.area.center().distance(&preload_area.center()).0 as u32);
|
|
|
|
|
|
|
|
|
|
tiles
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
|
|
|
/// Instruction for decoder to generate this tile
|
|
|
|
|
pub struct TileInstructions {
|
|
|
|
|
pub tiling: Tiling,
|
2023-04-16 01:36:38 +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
|
|
|
pub area: graphene::Rect,
|
|
|
|
|
pub coordinates: Coordinates,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl TileInstructions {
|
|
|
|
|
pub fn area_with_bleed(&self) -> graphene::Rect {
|
|
|
|
|
let bleed = self.tiling.bleed as f32;
|
|
|
|
|
self.area.inset_r(-bleed, -bleed)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Integer zoom levels are used because they are hashable
|
|
|
|
|
/// and ignore tiny float calculation errors.
|
|
|
|
|
pub fn zoom_to_level(zoom: f64) -> u32 {
|
2023-04-16 01:36:38 +02:00
|
|
|
(zoom * 10_f64.powi(ZOOM_SIGNIFICANT_DIGITS)) as u32
|
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 fn level_to_zoom(zoom_level: u32) -> f64 {
|
2023-04-16 01:36:38 +02:00
|
|
|
zoom_level as f64 * 10_f64.powi(-ZOOM_SIGNIFICANT_DIGITS)
|
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 fn zoom_normalize(zoom: f64) -> f64 {
|
|
|
|
|
level_to_zoom(zoom_to_level(zoom))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trait RectExt {
|
|
|
|
|
fn is_intersected(&self, b: &graphene::Rect) -> bool;
|
2023-04-16 01:36:38 +02:00
|
|
|
fn restrict(&self, max_width: f32, max_height: f32) -> Option<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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl RectExt for graphene::Rect {
|
|
|
|
|
fn is_intersected(&self, b: &graphene::Rect) -> bool {
|
|
|
|
|
self.intersection(b).is_some()
|
|
|
|
|
}
|
2023-04-16 01:36:38 +02:00
|
|
|
|
|
|
|
|
fn restrict(&self, max_width: f32, max_height: f32) -> Option<graphene::Rect> {
|
|
|
|
|
let mut x = self.x();
|
|
|
|
|
let mut y = self.y();
|
|
|
|
|
let mut width = self.width();
|
|
|
|
|
let mut height = self.height();
|
|
|
|
|
|
|
|
|
|
if x < 0. {
|
|
|
|
|
width += x;
|
|
|
|
|
x = 0.;
|
|
|
|
|
}
|
|
|
|
|
if y < 0. {
|
|
|
|
|
height += y;
|
|
|
|
|
y = 0.;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if x + width > max_width {
|
|
|
|
|
width = max_width - x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if y + height > max_height {
|
|
|
|
|
height = max_height - y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if width <= 0. || height <= 0. {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Some(Self::new(x, y, width, height))
|
|
|
|
|
}
|
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-04-02 22:22:00 +02:00
|
|
|
/// We always store [`FrameBuffer`]s in an [`ArcSwap`].
|
|
|
|
|
/// This trait adds convenience functions for this.
|
2023-03-15 22:35:59 +01:00
|
|
|
pub trait FrameBufferExt {
|
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
|
|
|
fn push(&self, tile: Tile);
|
2023-04-16 01:36:38 +02:00
|
|
|
fn push_tile(&self, tiling: Tiling, position: Coordinates, texture: gdk::Texture);
|
2023-03-15 22:35:59 +01:00
|
|
|
fn push_frame(&self, tile: Tile, dimensions: Coordinates, delay: Duration);
|
2023-04-13 01:19:53 +02:00
|
|
|
fn reset(&self);
|
2023-04-16 01:36:38 +02:00
|
|
|
fn get_layer_tiling_or_default(&self, zoom: f64, viewport: graphene::Rect) -> Tiling;
|
2023-03-15 22:35:59 +01:00
|
|
|
/// Return true if the next frame should be shown and removes the outdated frame
|
|
|
|
|
fn frame_timeout(&self, elapsed: Duration) -> bool;
|
|
|
|
|
/// Returns the number of currently buffered frames
|
|
|
|
|
fn n_frames(&self) -> usize;
|
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
|
|
|
fn set_original_dimensions(&self, size: Coordinates);
|
2023-03-10 19:08:26 +01:00
|
|
|
fn set_original_dimensions_full(
|
|
|
|
|
&self,
|
|
|
|
|
size: Coordinates,
|
|
|
|
|
dimension_details: ImageDimensionDetails,
|
|
|
|
|
);
|
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
|
|
|
fn set_update_sender(&self, sender: UpdateSender);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-15 22:35:59 +01:00
|
|
|
impl FrameBufferExt for ArcSwap<FrameBuffer> {
|
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
|
|
|
fn push(&self, tile: Tile) {
|
|
|
|
|
self.rcu(|tiling_store| {
|
|
|
|
|
let mut new_store = (**tiling_store).clone();
|
2023-03-15 22:35:59 +01:00
|
|
|
new_store.current().push(tile.clone());
|
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
|
|
|
Arc::new(new_store)
|
|
|
|
|
});
|
2023-03-15 22:35:59 +01:00
|
|
|
if let Some(updater) = &self.load().update_sender {
|
|
|
|
|
updater.send(DecoderUpdate::Redraw);
|
|
|
|
|
}
|
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-04-16 01:36:38 +02:00
|
|
|
fn push_tile(&self, tiling: Tiling, position: Coordinates, texture: gdk::Texture) {
|
|
|
|
|
self.rcu(|tiling_store| {
|
|
|
|
|
let mut new_store = (**tiling_store).clone();
|
|
|
|
|
new_store
|
|
|
|
|
.current()
|
|
|
|
|
.push_tile(tiling, position, texture.clone());
|
|
|
|
|
Arc::new(new_store)
|
|
|
|
|
});
|
|
|
|
|
if let Some(updater) = &self.load().update_sender {
|
|
|
|
|
updater.send(DecoderUpdate::Redraw);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-15 22:35:59 +01:00
|
|
|
fn push_frame(&self, tile: Tile, dimensions: Coordinates, delay: Duration) {
|
|
|
|
|
let mut store = TiledImage::default();
|
|
|
|
|
store.push(tile);
|
|
|
|
|
store.original_dimensions = Some(dimensions);
|
|
|
|
|
store.delay = delay;
|
|
|
|
|
|
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
|
|
|
self.rcu(|tiling_store| {
|
|
|
|
|
let mut new_store = (**tiling_store).clone();
|
2023-03-15 22:35:59 +01:00
|
|
|
new_store.images.push_back(store.clone());
|
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
|
|
|
Arc::new(new_store)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-13 01:19:53 +02:00
|
|
|
fn reset(&self) {
|
|
|
|
|
self.rcu(|tiling_store| {
|
|
|
|
|
let mut new_store = (**tiling_store).clone();
|
|
|
|
|
new_store.reset();
|
|
|
|
|
Arc::new(new_store)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-16 01:36:38 +02:00
|
|
|
fn get_layer_tiling_or_default(&self, zoom: f64, viewport: graphene::Rect) -> Tiling {
|
|
|
|
|
let mut tiling = None;
|
|
|
|
|
self.rcu(|tiling_store| {
|
|
|
|
|
let mut new_store = (**tiling_store).clone();
|
|
|
|
|
tiling = Some(
|
|
|
|
|
new_store
|
|
|
|
|
.current()
|
|
|
|
|
.get_layer_tiling_or_default(zoom, viewport),
|
|
|
|
|
);
|
|
|
|
|
Arc::new(new_store)
|
|
|
|
|
});
|
|
|
|
|
tiling.unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-15 22:35:59 +01:00
|
|
|
fn frame_timeout(&self, elapsed: Duration) -> bool {
|
|
|
|
|
if let Some(next_frame) = self.load().images.get(1) {
|
|
|
|
|
if elapsed >= next_frame.delay {
|
|
|
|
|
self.rcu(|tiling_store| {
|
|
|
|
|
let mut new_store = (**tiling_store).clone();
|
|
|
|
|
new_store.images.pop_front();
|
|
|
|
|
Arc::new(new_store)
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn n_frames(&self) -> usize {
|
|
|
|
|
self.load().images.len()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_original_dimensions(&self, size: Coordinates) {
|
|
|
|
|
self.set_original_dimensions_full(size, Default::default());
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-10 19:08:26 +01:00
|
|
|
fn set_original_dimensions_full(
|
|
|
|
|
&self,
|
|
|
|
|
size: Coordinates,
|
|
|
|
|
dimension_details: ImageDimensionDetails,
|
|
|
|
|
) {
|
|
|
|
|
self.rcu(|tiling_store| {
|
|
|
|
|
let mut new_store = (**tiling_store).clone();
|
2023-03-15 22:35:59 +01:00
|
|
|
new_store.current().original_dimensions = Some(size);
|
2023-03-10 19:08:26 +01:00
|
|
|
Arc::new(new_store)
|
|
|
|
|
});
|
2023-03-15 22:35:59 +01:00
|
|
|
|
|
|
|
|
if let Some(updater) = &self.load().update_sender {
|
|
|
|
|
updater.send(DecoderUpdate::Dimensions(dimension_details));
|
|
|
|
|
}
|
2023-03-10 19:08:26 +01: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
|
|
|
fn set_update_sender(&self, sender: UpdateSender) {
|
|
|
|
|
self.rcu(|tiling_store| {
|
|
|
|
|
let mut new_store = (**tiling_store).clone();
|
|
|
|
|
new_store.set_update_sender(sender.clone());
|
|
|
|
|
Arc::new(new_store)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|