Merge branch 'master' into wgpu/better-architecture
This commit is contained in:
commit
13289dbd19
41 changed files with 318 additions and 267 deletions
|
|
@ -1,53 +1,2 @@
|
||||||
[alias]
|
[alias]
|
||||||
lint = """
|
lint = "clippy --workspace --benches --all-features --no-deps -- -D warnings"
|
||||||
clippy --workspace --benches --no-deps -- \
|
|
||||||
-D warnings \
|
|
||||||
-A clippy::type_complexity \
|
|
||||||
-D clippy::semicolon_if_nothing_returned \
|
|
||||||
-D clippy::trivially-copy-pass-by-ref \
|
|
||||||
-D clippy::default_trait_access \
|
|
||||||
-D clippy::match-wildcard-for-single-variants \
|
|
||||||
-D clippy::redundant-closure-for-method-calls \
|
|
||||||
-D clippy::filter_map_next \
|
|
||||||
-D clippy::manual_let_else \
|
|
||||||
-D clippy::unused_async \
|
|
||||||
-D clippy::from_over_into \
|
|
||||||
-D clippy::needless_borrow \
|
|
||||||
-D clippy::new_without_default \
|
|
||||||
-D clippy::useless_conversion
|
|
||||||
"""
|
|
||||||
|
|
||||||
nitpick = """
|
|
||||||
clippy --workspace --benches --no-deps -- \
|
|
||||||
-D warnings \
|
|
||||||
-D clippy::pedantic \
|
|
||||||
-A clippy::type_complexity \
|
|
||||||
-A clippy::must_use_candidate \
|
|
||||||
-A clippy::return_self_not_must_use \
|
|
||||||
-A clippy::needless_pass_by_value \
|
|
||||||
-A clippy::cast_precision_loss \
|
|
||||||
-A clippy::cast_sign_loss \
|
|
||||||
-A clippy::cast_possible_truncation \
|
|
||||||
-A clippy::match_same_arms \
|
|
||||||
-A clippy::missing-errors-doc \
|
|
||||||
-A clippy::missing-panics-doc \
|
|
||||||
-A clippy::cast_lossless \
|
|
||||||
-A clippy::doc_markdown \
|
|
||||||
-A clippy::items_after_statements \
|
|
||||||
-A clippy::too_many_lines \
|
|
||||||
-A clippy::module_name_repetitions \
|
|
||||||
-A clippy::if_not_else \
|
|
||||||
-A clippy::redundant_else \
|
|
||||||
-A clippy::used_underscore_binding \
|
|
||||||
-A clippy::cast_possible_wrap \
|
|
||||||
-A clippy::unnecessary_wraps \
|
|
||||||
-A clippy::struct-excessive-bools \
|
|
||||||
-A clippy::float-cmp \
|
|
||||||
-A clippy::single_match_else \
|
|
||||||
-A clippy::unreadable_literal \
|
|
||||||
-A clippy::explicit_deref_methods \
|
|
||||||
-A clippy::map_unwrap_or \
|
|
||||||
-A clippy::unnested_or_patterns \
|
|
||||||
-A clippy::similar_names \
|
|
||||||
-A clippy::unused_self
|
|
||||||
"""
|
|
||||||
|
|
|
||||||
8
.github/workflows/check.yml
vendored
8
.github/workflows/check.yml
vendored
|
|
@ -1,14 +1,6 @@
|
||||||
name: Check
|
name: Check
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
jobs:
|
jobs:
|
||||||
benchmarks:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: hecrj/setup-rust-action@v2
|
|
||||||
- uses: actions/checkout@master
|
|
||||||
- name: Check benchmarks
|
|
||||||
run: cargo check --benches --all-features
|
|
||||||
|
|
||||||
wasm:
|
wasm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
|
|
|
||||||
7
.github/workflows/lint.yml
vendored
7
.github/workflows/lint.yml
vendored
|
|
@ -2,11 +2,16 @@ name: Lint
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
jobs:
|
jobs:
|
||||||
all:
|
all:
|
||||||
runs-on: macOS-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: hecrj/setup-rust-action@v2
|
- uses: hecrj/setup-rust-action@v2
|
||||||
with:
|
with:
|
||||||
components: clippy
|
components: clippy
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@master
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
export DEBIAN_FRONTED=noninteractive
|
||||||
|
sudo apt-get -qq update
|
||||||
|
sudo apt-get install -y libxkbcommon-dev libgtk-3-dev
|
||||||
- name: Check lints
|
- name: Check lints
|
||||||
run: cargo lint
|
run: cargo lint
|
||||||
|
|
|
||||||
42
Cargo.toml
42
Cargo.toml
|
|
@ -10,6 +10,9 @@ homepage.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
|
@ -74,6 +77,15 @@ thiserror.workspace = true
|
||||||
image.workspace = true
|
image.workspace = true
|
||||||
image.optional = true
|
image.optional = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
criterion = "0.5"
|
||||||
|
iced_wgpu.workspace = true
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "wgpu"
|
||||||
|
harness = false
|
||||||
|
required-features = ["canvas"]
|
||||||
|
|
||||||
[profile.release-opt]
|
[profile.release-opt]
|
||||||
inherits = "release"
|
inherits = "release"
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
@ -165,11 +177,27 @@ winapi = "0.3"
|
||||||
window_clipboard = "0.4.1"
|
window_clipboard = "0.4.1"
|
||||||
winit = { git = "https://github.com/iced-rs/winit.git", rev = "592bd152f6d5786fae7d918532d7db752c0d164f" }
|
winit = { git = "https://github.com/iced-rs/winit.git", rev = "592bd152f6d5786fae7d918532d7db752c0d164f" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[workspace.lints.rust]
|
||||||
criterion = "0.5"
|
rust_2018_idioms = "forbid"
|
||||||
iced_wgpu.workspace = true
|
missing_debug_implementations = "deny"
|
||||||
|
missing_docs = "deny"
|
||||||
|
unsafe_code = "deny"
|
||||||
|
unused_results = "deny"
|
||||||
|
|
||||||
[[bench]]
|
[workspace.lints.clippy]
|
||||||
name = "wgpu"
|
type-complexity = "allow"
|
||||||
harness = false
|
semicolon_if_nothing_returned = "deny"
|
||||||
required-features = ["canvas"]
|
trivially-copy-pass-by-ref = "deny"
|
||||||
|
default_trait_access = "deny"
|
||||||
|
match-wildcard-for-single-variants = "deny"
|
||||||
|
redundant-closure-for-method-calls = "deny"
|
||||||
|
filter_map_next = "deny"
|
||||||
|
manual_let_else = "deny"
|
||||||
|
unused_async = "deny"
|
||||||
|
from_over_into = "deny"
|
||||||
|
needless_borrow = "deny"
|
||||||
|
new_without_default = "deny"
|
||||||
|
useless_conversion = "deny"
|
||||||
|
|
||||||
|
[workspace.lints.rustdoc]
|
||||||
|
broken_intra_doc_links = "forbid"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![allow(missing_docs)]
|
||||||
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
|
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
|
||||||
|
|
||||||
use iced::alignment;
|
use iced::alignment;
|
||||||
|
|
@ -11,6 +12,7 @@ use iced_wgpu::Renderer;
|
||||||
criterion_main!(benches);
|
criterion_main!(benches);
|
||||||
criterion_group!(benches, wgpu_benchmark);
|
criterion_group!(benches, wgpu_benchmark);
|
||||||
|
|
||||||
|
#[allow(unused_results)]
|
||||||
pub fn wgpu_benchmark(c: &mut Criterion) {
|
pub fn wgpu_benchmark(c: &mut Criterion) {
|
||||||
c.bench_function("wgpu — canvas (light)", |b| benchmark(b, scene(10)));
|
c.bench_function("wgpu — canvas (light)", |b| benchmark(b, scene(10)));
|
||||||
c.bench_function("wgpu — canvas (heavy)", |b| benchmark(b, scene(1_000)));
|
c.bench_function("wgpu — canvas (heavy)", |b| benchmark(b, scene(1_000)));
|
||||||
|
|
@ -101,7 +103,7 @@ fn benchmark(
|
||||||
);
|
);
|
||||||
|
|
||||||
bencher.iter(|| {
|
bencher.iter(|| {
|
||||||
user_interface.draw(
|
let _ = user_interface.draw(
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&Theme::Dark,
|
&Theme::Dark,
|
||||||
&core::renderer::Style {
|
&core::renderer::Style {
|
||||||
|
|
@ -128,7 +130,6 @@ fn benchmark(
|
||||||
);
|
);
|
||||||
|
|
||||||
let submission = engine.submit(&queue, encoder);
|
let submission = engine.submit(&queue, encoder);
|
||||||
|
|
||||||
let _ = device.poll(wgpu::Maintain::WaitForSubmissionIndex(submission));
|
let _ = device.poll(wgpu::Maintain::WaitForSubmissionIndex(submission));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ homepage.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
auto-detect-theme = ["dep:dark-light"]
|
auto-detect-theme = ["dep:dark-light"]
|
||||||
advanced = []
|
advanced = []
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,6 @@
|
||||||
#![doc(
|
#![doc(
|
||||||
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
||||||
)]
|
)]
|
||||||
#![forbid(unsafe_code, rust_2018_idioms)]
|
|
||||||
#![deny(
|
|
||||||
missing_debug_implementations,
|
|
||||||
missing_docs,
|
|
||||||
unused_results,
|
|
||||||
rustdoc::broken_intra_doc_links
|
|
||||||
)]
|
|
||||||
pub mod alignment;
|
pub mod alignment;
|
||||||
pub mod border;
|
pub mod border;
|
||||||
pub mod clipboard;
|
pub mod clipboard;
|
||||||
|
|
|
||||||
|
|
@ -612,11 +612,19 @@ fn mix(a: Color, b: Color, factor: f32) -> Color {
|
||||||
|
|
||||||
fn readable(background: Color, text: Color) -> Color {
|
fn readable(background: Color, text: Color) -> Color {
|
||||||
if is_readable(background, text) {
|
if is_readable(background, text) {
|
||||||
text
|
return text;
|
||||||
} else if is_dark(background) {
|
}
|
||||||
|
|
||||||
|
let fallback = if is_dark(background) {
|
||||||
Color::WHITE
|
Color::WHITE
|
||||||
} else {
|
} else {
|
||||||
Color::BLACK
|
Color::BLACK
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_readable(background, fallback) {
|
||||||
|
fallback
|
||||||
|
} else {
|
||||||
|
fallback.inverse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ homepage.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,6 @@
|
||||||
#![doc(
|
#![doc(
|
||||||
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
||||||
)]
|
)]
|
||||||
#![forbid(unsafe_code, rust_2018_idioms)]
|
|
||||||
#![deny(
|
|
||||||
missing_debug_implementations,
|
|
||||||
missing_docs,
|
|
||||||
unused_results,
|
|
||||||
rustdoc::broken_intra_doc_links
|
|
||||||
)]
|
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
pub use futures;
|
pub use futures;
|
||||||
pub use iced_core as core;
|
pub use iced_core as core;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ homepage.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,6 @@
|
||||||
#![doc(
|
#![doc(
|
||||||
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
||||||
)]
|
)]
|
||||||
#![forbid(rust_2018_idioms)]
|
|
||||||
#![deny(
|
|
||||||
missing_debug_implementations,
|
|
||||||
missing_docs,
|
|
||||||
unsafe_code,
|
|
||||||
unused_results,
|
|
||||||
rustdoc::broken_intra_doc_links
|
|
||||||
)]
|
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
mod antialiasing;
|
mod antialiasing;
|
||||||
mod cached;
|
mod cached;
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,7 @@ use std::collections::hash_map;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
/// A store of recently used sections of text.
|
/// A store of recently used sections of text.
|
||||||
#[allow(missing_debug_implementations)]
|
#[derive(Debug, Default)]
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Cache {
|
pub struct Cache {
|
||||||
entries: FxHashMap<KeyHash, Entry>,
|
entries: FxHashMap<KeyHash, Entry>,
|
||||||
aliases: FxHashMap<KeyHash, KeyHash>,
|
aliases: FxHashMap<KeyHash, KeyHash>,
|
||||||
|
|
@ -135,7 +134,7 @@ impl Key<'_> {
|
||||||
pub type KeyHash = u64;
|
pub type KeyHash = u64;
|
||||||
|
|
||||||
/// A cache entry.
|
/// A cache entry.
|
||||||
#[allow(missing_debug_implementations)]
|
#[derive(Debug)]
|
||||||
pub struct Entry {
|
pub struct Entry {
|
||||||
/// The buffer of text, ready for drawing.
|
/// The buffer of text, ready for drawing.
|
||||||
pub buffer: cosmic_text::Buffer,
|
pub buffer: cosmic_text::Buffer,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ homepage.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
iced_core.workspace = true
|
iced_core.workspace = true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! A syntax highlighter for iced.
|
||||||
use iced_core as core;
|
use iced_core as core;
|
||||||
|
|
||||||
use crate::core::text::highlighter::{self, Format};
|
use crate::core::text::highlighter::{self, Format};
|
||||||
|
|
@ -16,6 +17,8 @@ static THEMES: Lazy<highlighting::ThemeSet> =
|
||||||
|
|
||||||
const LINES_PER_SNAPSHOT: usize = 50;
|
const LINES_PER_SNAPSHOT: usize = 50;
|
||||||
|
|
||||||
|
/// A syntax highlighter.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Highlighter {
|
pub struct Highlighter {
|
||||||
syntax: &'static parsing::SyntaxReference,
|
syntax: &'static parsing::SyntaxReference,
|
||||||
highlighter: highlighting::Highlighter<'static>,
|
highlighter: highlighting::Highlighter<'static>,
|
||||||
|
|
@ -131,25 +134,47 @@ impl highlighter::Highlighter for Highlighter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The settings of a [`Highlighter`].
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
|
/// The [`Theme`] of the [`Highlighter`].
|
||||||
|
///
|
||||||
|
/// It dictates the color scheme that will be used for highlighting.
|
||||||
pub theme: Theme,
|
pub theme: Theme,
|
||||||
|
/// The extension of the file to highlight.
|
||||||
|
///
|
||||||
|
/// The [`Highlighter`] will use the extension to automatically determine
|
||||||
|
/// the grammar to use for highlighting.
|
||||||
pub extension: String,
|
pub extension: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A highlight produced by a [`Highlighter`].
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Highlight(highlighting::StyleModifier);
|
pub struct Highlight(highlighting::StyleModifier);
|
||||||
|
|
||||||
impl Highlight {
|
impl Highlight {
|
||||||
|
/// Returns the color of this [`Highlight`].
|
||||||
|
///
|
||||||
|
/// If `None`, the original text color should be unchanged.
|
||||||
pub fn color(&self) -> Option<Color> {
|
pub fn color(&self) -> Option<Color> {
|
||||||
self.0.foreground.map(|color| {
|
self.0.foreground.map(|color| {
|
||||||
Color::from_rgba8(color.r, color.g, color.b, color.a as f32 / 255.0)
|
Color::from_rgba8(color.r, color.g, color.b, color.a as f32 / 255.0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the font of this [`Highlight`].
|
||||||
|
///
|
||||||
|
/// If `None`, the original font should be unchanged.
|
||||||
pub fn font(&self) -> Option<Font> {
|
pub fn font(&self) -> Option<Font> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [`Format`] of the [`Highlight`].
|
||||||
|
///
|
||||||
|
/// It contains both the [`color`] and the [`font`].
|
||||||
|
///
|
||||||
|
/// [`color`]: Self::color
|
||||||
|
/// [`font`]: Self::font
|
||||||
pub fn to_format(&self) -> Format<Font> {
|
pub fn to_format(&self) -> Format<Font> {
|
||||||
Format {
|
Format {
|
||||||
color: self.color(),
|
color: self.color(),
|
||||||
|
|
@ -158,6 +183,8 @@ impl Highlight {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A highlighting theme.
|
||||||
|
#[allow(missing_docs)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Theme {
|
pub enum Theme {
|
||||||
SolarizedDark,
|
SolarizedDark,
|
||||||
|
|
@ -168,6 +195,7 @@ pub enum Theme {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Theme {
|
impl Theme {
|
||||||
|
/// A static slice containing all the available themes.
|
||||||
pub const ALL: &'static [Self] = &[
|
pub const ALL: &'static [Self] = &[
|
||||||
Self::SolarizedDark,
|
Self::SolarizedDark,
|
||||||
Self::Base16Mocha,
|
Self::Base16Mocha,
|
||||||
|
|
@ -176,6 +204,7 @@ impl Theme {
|
||||||
Self::InspiredGitHub,
|
Self::InspiredGitHub,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/// Returns `true` if the [`Theme`] is dark, and false otherwise.
|
||||||
pub fn is_dark(self) -> bool {
|
pub fn is_dark(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::SolarizedDark
|
Self::SolarizedDark
|
||||||
|
|
@ -209,7 +238,7 @@ impl std::fmt::Display for Theme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ScopeRangeIterator {
|
struct ScopeRangeIterator {
|
||||||
ops: Vec<(usize, parsing::ScopeStackOp)>,
|
ops: Vec<(usize, parsing::ScopeStackOp)>,
|
||||||
line_length: usize,
|
line_length: usize,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ homepage.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
wgpu = ["iced_wgpu"]
|
wgpu = ["iced_wgpu"]
|
||||||
tiny-skia = ["iced_tiny_skia"]
|
tiny-skia = ["iced_tiny_skia"]
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Compose existing renderers and create type-safe fallback strategies.
|
||||||
use crate::core::image;
|
use crate::core::image;
|
||||||
use crate::core::renderer;
|
use crate::core::renderer;
|
||||||
use crate::core::svg;
|
use crate::core::svg;
|
||||||
|
|
@ -8,24 +9,31 @@ use crate::graphics;
|
||||||
use crate::graphics::compositor;
|
use crate::graphics::compositor;
|
||||||
use crate::graphics::mesh;
|
use crate::graphics::mesh;
|
||||||
|
|
||||||
pub enum Renderer<L, R> {
|
/// A renderer `A` with a fallback strategy `B`.
|
||||||
Left(L),
|
///
|
||||||
Right(R),
|
/// This type can be used to easily compose existing renderers and
|
||||||
|
/// create custom, type-safe fallback strategies.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Renderer<A, B> {
|
||||||
|
/// The primary rendering option.
|
||||||
|
Primary(A),
|
||||||
|
/// The secondary (or fallback) rendering option.
|
||||||
|
Secondary(B),
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! delegate {
|
macro_rules! delegate {
|
||||||
($renderer:expr, $name:ident, $body:expr) => {
|
($renderer:expr, $name:ident, $body:expr) => {
|
||||||
match $renderer {
|
match $renderer {
|
||||||
Self::Left($name) => $body,
|
Self::Primary($name) => $body,
|
||||||
Self::Right($name) => $body,
|
Self::Secondary($name) => $body,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, R> core::Renderer for Renderer<L, R>
|
impl<A, B> core::Renderer for Renderer<A, B>
|
||||||
where
|
where
|
||||||
L: core::Renderer,
|
A: core::Renderer,
|
||||||
R: core::Renderer,
|
B: core::Renderer,
|
||||||
{
|
{
|
||||||
fn fill_quad(
|
fn fill_quad(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -60,22 +68,22 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, R> core::text::Renderer for Renderer<L, R>
|
impl<A, B> core::text::Renderer for Renderer<A, B>
|
||||||
where
|
where
|
||||||
L: core::text::Renderer,
|
A: core::text::Renderer,
|
||||||
R: core::text::Renderer<
|
B: core::text::Renderer<
|
||||||
Font = L::Font,
|
Font = A::Font,
|
||||||
Paragraph = L::Paragraph,
|
Paragraph = A::Paragraph,
|
||||||
Editor = L::Editor,
|
Editor = A::Editor,
|
||||||
>,
|
>,
|
||||||
{
|
{
|
||||||
type Font = L::Font;
|
type Font = A::Font;
|
||||||
type Paragraph = L::Paragraph;
|
type Paragraph = A::Paragraph;
|
||||||
type Editor = L::Editor;
|
type Editor = A::Editor;
|
||||||
|
|
||||||
const ICON_FONT: Self::Font = L::ICON_FONT;
|
const ICON_FONT: Self::Font = A::ICON_FONT;
|
||||||
const CHECKMARK_ICON: char = L::CHECKMARK_ICON;
|
const CHECKMARK_ICON: char = A::CHECKMARK_ICON;
|
||||||
const ARROW_DOWN_ICON: char = L::ARROW_DOWN_ICON;
|
const ARROW_DOWN_ICON: char = A::ARROW_DOWN_ICON;
|
||||||
|
|
||||||
fn default_font(&self) -> Self::Font {
|
fn default_font(&self) -> Self::Font {
|
||||||
delegate!(self, renderer, renderer.default_font())
|
delegate!(self, renderer, renderer.default_font())
|
||||||
|
|
@ -132,12 +140,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, R> image::Renderer for Renderer<L, R>
|
impl<A, B> image::Renderer for Renderer<A, B>
|
||||||
where
|
where
|
||||||
L: image::Renderer,
|
A: image::Renderer,
|
||||||
R: image::Renderer<Handle = L::Handle>,
|
B: image::Renderer<Handle = A::Handle>,
|
||||||
{
|
{
|
||||||
type Handle = L::Handle;
|
type Handle = A::Handle;
|
||||||
|
|
||||||
fn measure_image(&self, handle: &Self::Handle) -> Size<u32> {
|
fn measure_image(&self, handle: &Self::Handle) -> Size<u32> {
|
||||||
delegate!(self, renderer, renderer.measure_image(handle))
|
delegate!(self, renderer, renderer.measure_image(handle))
|
||||||
|
|
@ -157,10 +165,10 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, R> svg::Renderer for Renderer<L, R>
|
impl<A, B> svg::Renderer for Renderer<A, B>
|
||||||
where
|
where
|
||||||
L: svg::Renderer,
|
A: svg::Renderer,
|
||||||
R: svg::Renderer,
|
B: svg::Renderer,
|
||||||
{
|
{
|
||||||
fn measure_svg(&self, handle: &svg::Handle) -> Size<u32> {
|
fn measure_svg(&self, handle: &svg::Handle) -> Size<u32> {
|
||||||
delegate!(self, renderer, renderer.measure_svg(handle))
|
delegate!(self, renderer, renderer.measure_svg(handle))
|
||||||
|
|
@ -176,37 +184,49 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, R> mesh::Renderer for Renderer<L, R>
|
impl<A, B> mesh::Renderer for Renderer<A, B>
|
||||||
where
|
where
|
||||||
L: mesh::Renderer,
|
A: mesh::Renderer,
|
||||||
R: mesh::Renderer,
|
B: mesh::Renderer,
|
||||||
{
|
{
|
||||||
fn draw_mesh(&mut self, mesh: graphics::Mesh) {
|
fn draw_mesh(&mut self, mesh: graphics::Mesh) {
|
||||||
delegate!(self, renderer, renderer.draw_mesh(mesh));
|
delegate!(self, renderer, renderer.draw_mesh(mesh));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Compositor<L, R>
|
/// A compositor `A` with a fallback strategy `B`.
|
||||||
|
///
|
||||||
|
/// It works analogously to [`Renderer`].
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Compositor<A, B>
|
||||||
where
|
where
|
||||||
L: graphics::Compositor,
|
A: graphics::Compositor,
|
||||||
R: graphics::Compositor,
|
B: graphics::Compositor,
|
||||||
{
|
{
|
||||||
Left(L),
|
/// The primary compositing option.
|
||||||
Right(R),
|
Primary(A),
|
||||||
|
/// The secondary (or fallback) compositing option.
|
||||||
|
Secondary(B),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Surface<L, R> {
|
/// A surface `A` with a fallback strategy `B`.
|
||||||
Left(L),
|
///
|
||||||
Right(R),
|
/// It works analogously to [`Renderer`].
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Surface<A, B> {
|
||||||
|
/// The primary surface option.
|
||||||
|
Primary(A),
|
||||||
|
/// The secondary (or fallback) surface option.
|
||||||
|
Secondary(B),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, R> graphics::Compositor for Compositor<L, R>
|
impl<A, B> graphics::Compositor for Compositor<A, B>
|
||||||
where
|
where
|
||||||
L: graphics::Compositor,
|
A: graphics::Compositor,
|
||||||
R: graphics::Compositor,
|
B: graphics::Compositor,
|
||||||
{
|
{
|
||||||
type Renderer = Renderer<L::Renderer, R::Renderer>;
|
type Renderer = Renderer<A::Renderer, B::Renderer>;
|
||||||
type Surface = Surface<L::Surface, R::Surface>;
|
type Surface = Surface<A::Surface, B::Surface>;
|
||||||
|
|
||||||
async fn with_backend<W: compositor::Window + Clone>(
|
async fn with_backend<W: compositor::Window + Clone>(
|
||||||
settings: graphics::Settings,
|
settings: graphics::Settings,
|
||||||
|
|
@ -237,19 +257,19 @@ where
|
||||||
let mut errors = vec![];
|
let mut errors = vec![];
|
||||||
|
|
||||||
for backend in candidates.iter().map(Option::as_deref) {
|
for backend in candidates.iter().map(Option::as_deref) {
|
||||||
match L::with_backend(settings, compatible_window.clone(), backend)
|
match A::with_backend(settings, compatible_window.clone(), backend)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(compositor) => return Ok(Self::Left(compositor)),
|
Ok(compositor) => return Ok(Self::Primary(compositor)),
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
errors.push(error);
|
errors.push(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match R::with_backend(settings, compatible_window.clone(), backend)
|
match B::with_backend(settings, compatible_window.clone(), backend)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(compositor) => return Ok(Self::Right(compositor)),
|
Ok(compositor) => return Ok(Self::Secondary(compositor)),
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
errors.push(error);
|
errors.push(error);
|
||||||
}
|
}
|
||||||
|
|
@ -261,11 +281,11 @@ where
|
||||||
|
|
||||||
fn create_renderer(&self) -> Self::Renderer {
|
fn create_renderer(&self) -> Self::Renderer {
|
||||||
match self {
|
match self {
|
||||||
Self::Left(compositor) => {
|
Self::Primary(compositor) => {
|
||||||
Renderer::Left(compositor.create_renderer())
|
Renderer::Primary(compositor.create_renderer())
|
||||||
}
|
}
|
||||||
Self::Right(compositor) => {
|
Self::Secondary(compositor) => {
|
||||||
Renderer::Right(compositor.create_renderer())
|
Renderer::Secondary(compositor.create_renderer())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -277,12 +297,12 @@ where
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> Self::Surface {
|
) -> Self::Surface {
|
||||||
match self {
|
match self {
|
||||||
Self::Left(compositor) => {
|
Self::Primary(compositor) => Surface::Primary(
|
||||||
Surface::Left(compositor.create_surface(window, width, height))
|
compositor.create_surface(window, width, height),
|
||||||
}
|
),
|
||||||
Self::Right(compositor) => {
|
Self::Secondary(compositor) => Surface::Secondary(
|
||||||
Surface::Right(compositor.create_surface(window, width, height))
|
compositor.create_surface(window, width, height),
|
||||||
}
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -293,10 +313,10 @@ where
|
||||||
height: u32,
|
height: u32,
|
||||||
) {
|
) {
|
||||||
match (self, surface) {
|
match (self, surface) {
|
||||||
(Self::Left(compositor), Surface::Left(surface)) => {
|
(Self::Primary(compositor), Surface::Primary(surface)) => {
|
||||||
compositor.configure_surface(surface, width, height);
|
compositor.configure_surface(surface, width, height);
|
||||||
}
|
}
|
||||||
(Self::Right(compositor), Surface::Right(surface)) => {
|
(Self::Secondary(compositor), Surface::Secondary(surface)) => {
|
||||||
compositor.configure_surface(surface, width, height);
|
compositor.configure_surface(surface, width, height);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
@ -317,9 +337,9 @@ where
|
||||||
) -> Result<(), compositor::SurfaceError> {
|
) -> Result<(), compositor::SurfaceError> {
|
||||||
match (self, renderer, surface) {
|
match (self, renderer, surface) {
|
||||||
(
|
(
|
||||||
Self::Left(compositor),
|
Self::Primary(compositor),
|
||||||
Renderer::Left(renderer),
|
Renderer::Primary(renderer),
|
||||||
Surface::Left(surface),
|
Surface::Primary(surface),
|
||||||
) => compositor.present(
|
) => compositor.present(
|
||||||
renderer,
|
renderer,
|
||||||
surface,
|
surface,
|
||||||
|
|
@ -328,9 +348,9 @@ where
|
||||||
overlay,
|
overlay,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Self::Right(compositor),
|
Self::Secondary(compositor),
|
||||||
Renderer::Right(renderer),
|
Renderer::Secondary(renderer),
|
||||||
Surface::Right(surface),
|
Surface::Secondary(surface),
|
||||||
) => compositor.present(
|
) => compositor.present(
|
||||||
renderer,
|
renderer,
|
||||||
surface,
|
surface,
|
||||||
|
|
@ -352,9 +372,9 @@ where
|
||||||
) -> Vec<u8> {
|
) -> Vec<u8> {
|
||||||
match (self, renderer, surface) {
|
match (self, renderer, surface) {
|
||||||
(
|
(
|
||||||
Self::Left(compositor),
|
Self::Primary(compositor),
|
||||||
Renderer::Left(renderer),
|
Renderer::Primary(renderer),
|
||||||
Surface::Left(surface),
|
Surface::Primary(surface),
|
||||||
) => compositor.screenshot(
|
) => compositor.screenshot(
|
||||||
renderer,
|
renderer,
|
||||||
surface,
|
surface,
|
||||||
|
|
@ -363,9 +383,9 @@ where
|
||||||
overlay,
|
overlay,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Self::Right(compositor),
|
Self::Secondary(compositor),
|
||||||
Renderer::Right(renderer),
|
Renderer::Secondary(renderer),
|
||||||
Surface::Right(surface),
|
Surface::Secondary(surface),
|
||||||
) => compositor.screenshot(
|
) => compositor.screenshot(
|
||||||
renderer,
|
renderer,
|
||||||
surface,
|
surface,
|
||||||
|
|
@ -379,10 +399,10 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wgpu")]
|
#[cfg(feature = "wgpu")]
|
||||||
impl<L, R> iced_wgpu::primitive::pipeline::Renderer for Renderer<L, R>
|
impl<A, B> iced_wgpu::primitive::pipeline::Renderer for Renderer<A, B>
|
||||||
where
|
where
|
||||||
L: iced_wgpu::primitive::pipeline::Renderer,
|
A: iced_wgpu::primitive::pipeline::Renderer,
|
||||||
R: core::Renderer,
|
B: core::Renderer,
|
||||||
{
|
{
|
||||||
fn draw_pipeline_primitive(
|
fn draw_pipeline_primitive(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -390,10 +410,10 @@ where
|
||||||
primitive: impl iced_wgpu::primitive::pipeline::Primitive,
|
primitive: impl iced_wgpu::primitive::pipeline::Primitive,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self {
|
||||||
Self::Left(renderer) => {
|
Self::Primary(renderer) => {
|
||||||
renderer.draw_pipeline_primitive(bounds, primitive);
|
renderer.draw_pipeline_primitive(bounds, primitive);
|
||||||
}
|
}
|
||||||
Self::Right(_) => {
|
Self::Secondary(_) => {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"Custom shader primitive is not supported with this renderer."
|
"Custom shader primitive is not supported with this renderer."
|
||||||
);
|
);
|
||||||
|
|
@ -409,27 +429,31 @@ mod geometry {
|
||||||
use crate::graphics::geometry::{self, Fill, Path, Stroke, Text};
|
use crate::graphics::geometry::{self, Fill, Path, Stroke, Text};
|
||||||
use crate::graphics::Cached;
|
use crate::graphics::Cached;
|
||||||
|
|
||||||
impl<L, R> geometry::Renderer for Renderer<L, R>
|
impl<A, B> geometry::Renderer for Renderer<A, B>
|
||||||
where
|
where
|
||||||
L: geometry::Renderer,
|
A: geometry::Renderer,
|
||||||
R: geometry::Renderer,
|
B: geometry::Renderer,
|
||||||
{
|
{
|
||||||
type Geometry = Geometry<L::Geometry, R::Geometry>;
|
type Geometry = Geometry<A::Geometry, B::Geometry>;
|
||||||
type Frame = Frame<L::Frame, R::Frame>;
|
type Frame = Frame<A::Frame, B::Frame>;
|
||||||
|
|
||||||
fn new_frame(&self, size: iced_graphics::core::Size) -> Self::Frame {
|
fn new_frame(&self, size: iced_graphics::core::Size) -> Self::Frame {
|
||||||
match self {
|
match self {
|
||||||
Self::Left(renderer) => Frame::Left(renderer.new_frame(size)),
|
Self::Primary(renderer) => {
|
||||||
Self::Right(renderer) => Frame::Right(renderer.new_frame(size)),
|
Frame::Primary(renderer.new_frame(size))
|
||||||
|
}
|
||||||
|
Self::Secondary(renderer) => {
|
||||||
|
Frame::Secondary(renderer.new_frame(size))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_geometry(&mut self, geometry: Self::Geometry) {
|
fn draw_geometry(&mut self, geometry: Self::Geometry) {
|
||||||
match (self, geometry) {
|
match (self, geometry) {
|
||||||
(Self::Left(renderer), Geometry::Left(geometry)) => {
|
(Self::Primary(renderer), Geometry::Primary(geometry)) => {
|
||||||
renderer.draw_geometry(geometry);
|
renderer.draw_geometry(geometry);
|
||||||
}
|
}
|
||||||
(Self::Right(renderer), Geometry::Right(geometry)) => {
|
(Self::Secondary(renderer), Geometry::Secondary(geometry)) => {
|
||||||
renderer.draw_geometry(geometry);
|
renderer.draw_geometry(geometry);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
@ -437,56 +461,59 @@ mod geometry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Geometry<L, R> {
|
pub enum Geometry<A, B> {
|
||||||
Left(L),
|
Primary(A),
|
||||||
Right(R),
|
Secondary(B),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, R> Cached for Geometry<L, R>
|
impl<A, B> Cached for Geometry<A, B>
|
||||||
where
|
where
|
||||||
L: Cached,
|
A: Cached,
|
||||||
R: Cached,
|
B: Cached,
|
||||||
{
|
{
|
||||||
type Cache = Geometry<L::Cache, R::Cache>;
|
type Cache = Geometry<A::Cache, B::Cache>;
|
||||||
|
|
||||||
fn load(cache: &Self::Cache) -> Self {
|
fn load(cache: &Self::Cache) -> Self {
|
||||||
match cache {
|
match cache {
|
||||||
Geometry::Left(cache) => Self::Left(L::load(cache)),
|
Geometry::Primary(cache) => Self::Primary(A::load(cache)),
|
||||||
Geometry::Right(cache) => Self::Right(R::load(cache)),
|
Geometry::Secondary(cache) => Self::Secondary(B::load(cache)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cache(self, previous: Option<Self::Cache>) -> Self::Cache {
|
fn cache(self, previous: Option<Self::Cache>) -> Self::Cache {
|
||||||
match (self, previous) {
|
match (self, previous) {
|
||||||
(Self::Left(geometry), Some(Geometry::Left(previous))) => {
|
(
|
||||||
Geometry::Left(geometry.cache(Some(previous)))
|
Self::Primary(geometry),
|
||||||
|
Some(Geometry::Primary(previous)),
|
||||||
|
) => Geometry::Primary(geometry.cache(Some(previous))),
|
||||||
|
(Self::Primary(geometry), None) => {
|
||||||
|
Geometry::Primary(geometry.cache(None))
|
||||||
}
|
}
|
||||||
(Self::Left(geometry), None) => {
|
(
|
||||||
Geometry::Left(geometry.cache(None))
|
Self::Secondary(geometry),
|
||||||
}
|
Some(Geometry::Secondary(previous)),
|
||||||
(Self::Right(geometry), Some(Geometry::Right(previous))) => {
|
) => Geometry::Secondary(geometry.cache(Some(previous))),
|
||||||
Geometry::Right(geometry.cache(Some(previous)))
|
(Self::Secondary(geometry), None) => {
|
||||||
}
|
Geometry::Secondary(geometry.cache(None))
|
||||||
(Self::Right(geometry), None) => {
|
|
||||||
Geometry::Right(geometry.cache(None))
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Frame<L, R> {
|
#[derive(Debug)]
|
||||||
Left(L),
|
pub enum Frame<A, B> {
|
||||||
Right(R),
|
Primary(A),
|
||||||
|
Secondary(B),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, R> geometry::frame::Backend for Frame<L, R>
|
impl<A, B> geometry::frame::Backend for Frame<A, B>
|
||||||
where
|
where
|
||||||
L: geometry::frame::Backend,
|
A: geometry::frame::Backend,
|
||||||
R: geometry::frame::Backend,
|
B: geometry::frame::Backend,
|
||||||
{
|
{
|
||||||
type Geometry = Geometry<L::Geometry, R::Geometry>;
|
type Geometry = Geometry<A::Geometry, B::Geometry>;
|
||||||
|
|
||||||
fn width(&self) -> f32 {
|
fn width(&self) -> f32 {
|
||||||
delegate!(self, frame, frame.width())
|
delegate!(self, frame, frame.width())
|
||||||
|
|
@ -535,17 +562,17 @@ mod geometry {
|
||||||
|
|
||||||
fn draft(&mut self, bounds: Rectangle) -> Self {
|
fn draft(&mut self, bounds: Rectangle) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Left(frame) => Self::Left(frame.draft(bounds)),
|
Self::Primary(frame) => Self::Primary(frame.draft(bounds)),
|
||||||
Self::Right(frame) => Self::Right(frame.draft(bounds)),
|
Self::Secondary(frame) => Self::Secondary(frame.draft(bounds)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paste(&mut self, frame: Self, at: Point) {
|
fn paste(&mut self, frame: Self, at: Point) {
|
||||||
match (self, frame) {
|
match (self, frame) {
|
||||||
(Self::Left(target), Self::Left(source)) => {
|
(Self::Primary(target), Self::Primary(source)) => {
|
||||||
target.paste(source, at);
|
target.paste(source, at);
|
||||||
}
|
}
|
||||||
(Self::Right(target), Self::Right(source)) => {
|
(Self::Secondary(target), Self::Secondary(source)) => {
|
||||||
target.paste(source, at);
|
target.paste(source, at);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
@ -570,17 +597,21 @@ mod geometry {
|
||||||
|
|
||||||
fn into_geometry(self) -> Self::Geometry {
|
fn into_geometry(self) -> Self::Geometry {
|
||||||
match self {
|
match self {
|
||||||
Frame::Left(frame) => Geometry::Left(frame.into_geometry()),
|
Frame::Primary(frame) => {
|
||||||
Frame::Right(frame) => Geometry::Right(frame.into_geometry()),
|
Geometry::Primary(frame.into_geometry())
|
||||||
|
}
|
||||||
|
Frame::Secondary(frame) => {
|
||||||
|
Geometry::Secondary(frame.into_geometry())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L, R> compositor::Default for Renderer<L, R>
|
impl<A, B> compositor::Default for Renderer<A, B>
|
||||||
where
|
where
|
||||||
L: compositor::Default,
|
A: compositor::Default,
|
||||||
R: compositor::Default,
|
B: compositor::Default,
|
||||||
{
|
{
|
||||||
type Compositor = Compositor<L::Compositor, R::Compositor>;
|
type Compositor = Compositor<A::Compositor, B::Compositor>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#![forbid(rust_2018_idioms)]
|
//! The official renderer for iced.
|
||||||
#![deny(unsafe_code, unused_results, rustdoc::broken_intra_doc_links)]
|
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
#[cfg(feature = "wgpu")]
|
#[cfg(feature = "wgpu")]
|
||||||
pub use iced_wgpu as wgpu;
|
pub use iced_wgpu as wgpu;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ homepage.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
debug = []
|
debug = []
|
||||||
multi-window = []
|
multi-window = []
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,6 @@
|
||||||
#![doc(
|
#![doc(
|
||||||
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
||||||
)]
|
)]
|
||||||
#![forbid(unsafe_code, rust_2018_idioms)]
|
|
||||||
#![deny(
|
|
||||||
missing_debug_implementations,
|
|
||||||
missing_docs,
|
|
||||||
unused_results,
|
|
||||||
rustdoc::broken_intra_doc_links
|
|
||||||
)]
|
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
pub mod clipboard;
|
pub mod clipboard;
|
||||||
pub mod command;
|
pub mod command;
|
||||||
|
|
|
||||||
|
|
@ -165,13 +165,6 @@
|
||||||
#![doc(
|
#![doc(
|
||||||
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
||||||
)]
|
)]
|
||||||
#![forbid(rust_2018_idioms, unsafe_code)]
|
|
||||||
#![deny(
|
|
||||||
missing_debug_implementations,
|
|
||||||
missing_docs,
|
|
||||||
unused_results,
|
|
||||||
rustdoc::broken_intra_doc_links
|
|
||||||
)]
|
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
use iced_widget::graphics;
|
use iced_widget::graphics;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ homepage.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
image = ["iced_graphics/image"]
|
image = ["iced_graphics/image"]
|
||||||
svg = ["resvg"]
|
svg = ["resvg"]
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use crate::window;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Backend {
|
pub struct Backend {
|
||||||
text_pipeline: crate::text::Pipeline,
|
text_pipeline: crate::text::Pipeline,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use crate::graphics::geometry::{self, Path, Style, Text};
|
||||||
use crate::graphics::Gradient;
|
use crate::graphics::Gradient;
|
||||||
use crate::primitive::{self, Primitive};
|
use crate::primitive::{self, Primitive};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Frame {
|
pub struct Frame {
|
||||||
size: Size,
|
size: Size,
|
||||||
transform: tiny_skia::Transform,
|
transform: tiny_skia::Transform,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#![forbid(rust_2018_idioms)]
|
#![allow(missing_docs)]
|
||||||
#![deny(unsafe_code, unused_results, rustdoc::broken_intra_doc_links)]
|
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
pub mod window;
|
pub mod window;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::hash_map;
|
use std::collections::hash_map;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Pipeline {
|
pub struct Pipeline {
|
||||||
cache: RefCell<Cache>,
|
cache: RefCell<Cache>,
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +69,7 @@ impl Pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
struct Cache {
|
struct Cache {
|
||||||
entries: FxHashMap<u64, Option<Entry>>,
|
entries: FxHashMap<u64, Option<Entry>>,
|
||||||
hits: FxHashSet<u64>,
|
hits: FxHashSet<u64>,
|
||||||
|
|
@ -119,6 +120,7 @@ impl Cache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct Entry {
|
struct Entry {
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::hash_map;
|
use std::collections::hash_map;
|
||||||
|
|
||||||
#[allow(missing_debug_implementations)]
|
#[derive(Debug)]
|
||||||
pub struct Pipeline {
|
pub struct Pipeline {
|
||||||
glyph_cache: GlyphCache,
|
glyph_cache: GlyphCache,
|
||||||
cache: RefCell<Cache>,
|
cache: RefCell<Cache>,
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use std::cell::RefCell;
|
||||||
use std::collections::hash_map;
|
use std::collections::hash_map;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Pipeline {
|
pub struct Pipeline {
|
||||||
cache: RefCell<Cache>,
|
cache: RefCell<Cache>,
|
||||||
}
|
}
|
||||||
|
|
@ -203,3 +204,13 @@ impl Cache {
|
||||||
self.raster_hits.clear();
|
self.raster_hits.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for Cache {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("Cache")
|
||||||
|
.field("tree_hits", &self.tree_hits)
|
||||||
|
.field("rasters", &self.rasters)
|
||||||
|
.field("raster_hits", &self.raster_hits)
|
||||||
|
.finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,13 @@ use crate::{Backend, Primitive, Renderer, Settings};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Compositor {
|
pub struct Compositor {
|
||||||
context: softbuffer::Context<Box<dyn compositor::Window>>,
|
context: softbuffer::Context<Box<dyn compositor::Window>>,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Surface {
|
pub struct Surface {
|
||||||
window: softbuffer::Surface<
|
window: softbuffer::Surface<
|
||||||
Box<dyn compositor::Window>,
|
Box<dyn compositor::Window>,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ homepage.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,13 @@ pub struct Frame {
|
||||||
stroke_tessellator: tessellation::StrokeTessellator,
|
stroke_tessellator: tessellation::StrokeTessellator,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Geometry {
|
pub enum Geometry {
|
||||||
Live { meshes: Vec<Mesh>, text: Vec<Text> },
|
Live { meshes: Vec<Mesh>, text: Vec<Text> },
|
||||||
Cached(Cache),
|
Cached(Cache),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Cache {
|
pub struct Cache {
|
||||||
pub meshes: Option<triangle::Cache>,
|
pub meshes: Option<triangle::Cache>,
|
||||||
pub text: Option<text::Cache>,
|
pub text: Option<text::Cache>,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
pub use crate::graphics::Image;
|
pub use crate::graphics::Image;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Batch;
|
pub struct Batch;
|
||||||
|
|
||||||
impl Batch {
|
impl Batch {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use crate::quad::{self, Quad};
|
||||||
use crate::text::{self, Text};
|
use crate::text::{self, Text};
|
||||||
use crate::triangle;
|
use crate::triangle;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Layer {
|
pub struct Layer {
|
||||||
pub bounds: Rectangle,
|
pub bounds: Rectangle,
|
||||||
pub quads: quad::Batch,
|
pub quads: quad::Batch,
|
||||||
|
|
@ -28,6 +29,7 @@ impl Default for Layer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Stack {
|
pub struct Stack {
|
||||||
layers: Vec<Layer>,
|
layers: Vec<Layer>,
|
||||||
transformations: Vec<Transformation>,
|
transformations: Vec<Transformation>,
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,8 @@
|
||||||
#![doc(
|
#![doc(
|
||||||
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
||||||
)]
|
)]
|
||||||
#![forbid(rust_2018_idioms)]
|
|
||||||
#![deny(
|
|
||||||
// missing_debug_implementations,
|
|
||||||
//missing_docs,
|
|
||||||
unsafe_code,
|
|
||||||
unused_results,
|
|
||||||
rustdoc::broken_intra_doc_links
|
|
||||||
)]
|
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
|
#![allow(missing_docs)]
|
||||||
pub mod layer;
|
pub mod layer;
|
||||||
pub mod primitive;
|
pub mod primitive;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ const INITIAL_VERTEX_COUNT: usize = 1_000;
|
||||||
|
|
||||||
pub type Batch = Vec<Item>;
|
pub type Batch = Vec<Item>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Item {
|
pub enum Item {
|
||||||
Group {
|
Group {
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ homepage.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,6 @@
|
||||||
#![doc(
|
#![doc(
|
||||||
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
||||||
)]
|
)]
|
||||||
#![forbid(unsafe_code, rust_2018_idioms)]
|
|
||||||
#![deny(
|
|
||||||
missing_debug_implementations,
|
|
||||||
missing_docs,
|
|
||||||
unused_results,
|
|
||||||
rustdoc::broken_intra_doc_links
|
|
||||||
)]
|
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
pub use iced_renderer as renderer;
|
pub use iced_renderer as renderer;
|
||||||
pub use iced_renderer::graphics;
|
pub use iced_renderer::graphics;
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,21 @@ where
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the text size of the [`TextEditor`].
|
||||||
|
pub fn size(mut self, size: impl Into<Pixels>) -> Self {
|
||||||
|
self.text_size = Some(size.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the [`text::LineHeight`] of the [`TextEditor`].
|
||||||
|
pub fn line_height(
|
||||||
|
mut self,
|
||||||
|
line_height: impl Into<text::LineHeight>,
|
||||||
|
) -> Self {
|
||||||
|
self.line_height = line_height.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the [`Padding`] of the [`TextEditor`].
|
/// Sets the [`Padding`] of the [`TextEditor`].
|
||||||
pub fn padding(mut self, padding: impl Into<Padding>) -> Self {
|
pub fn padding(mut self, padding: impl Into<Padding>) -> Self {
|
||||||
self.padding = padding.into();
|
self.padding = padding.into();
|
||||||
|
|
|
||||||
|
|
@ -713,7 +713,8 @@ where
|
||||||
|
|
||||||
match key.as_ref() {
|
match key.as_ref() {
|
||||||
keyboard::Key::Character("c")
|
keyboard::Key::Character("c")
|
||||||
if state.keyboard_modifiers.command() =>
|
if state.keyboard_modifiers.command()
|
||||||
|
&& !self.is_secure =>
|
||||||
{
|
{
|
||||||
if let Some((start, end)) =
|
if let Some((start, end)) =
|
||||||
state.cursor.selection(&self.value)
|
state.cursor.selection(&self.value)
|
||||||
|
|
@ -727,7 +728,8 @@ where
|
||||||
return event::Status::Captured;
|
return event::Status::Captured;
|
||||||
}
|
}
|
||||||
keyboard::Key::Character("x")
|
keyboard::Key::Character("x")
|
||||||
if state.keyboard_modifiers.command() =>
|
if state.keyboard_modifiers.command()
|
||||||
|
&& !self.is_secure =>
|
||||||
{
|
{
|
||||||
if let Some((start, end)) =
|
if let Some((start, end)) =
|
||||||
state.cursor.selection(&self.value)
|
state.cursor.selection(&self.value)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ homepage.workspace = true
|
||||||
categories.workspace = true
|
categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
|
default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
|
||||||
debug = ["iced_runtime/debug"]
|
debug = ["iced_runtime/debug"]
|
||||||
|
|
@ -41,3 +44,4 @@ winapi.workspace = true
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
web-sys.workspace = true
|
web-sys.workspace = true
|
||||||
web-sys.features = ["Document", "Window"]
|
web-sys.features = ["Document", "Window"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,6 @@
|
||||||
#![doc(
|
#![doc(
|
||||||
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
|
||||||
)]
|
)]
|
||||||
#![forbid(rust_2018_idioms)]
|
|
||||||
#![deny(
|
|
||||||
missing_debug_implementations,
|
|
||||||
missing_docs,
|
|
||||||
unused_results,
|
|
||||||
unsafe_code,
|
|
||||||
rustdoc::broken_intra_doc_links
|
|
||||||
)]
|
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
pub use iced_graphics as graphics;
|
pub use iced_graphics as graphics;
|
||||||
pub use iced_runtime as runtime;
|
pub use iced_runtime as runtime;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue