mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Autogenerate default cast in#[ty]
unless cast
is specified
This commit is contained in:
parent
1834ebc529
commit
37249c20f7
@ -116,6 +116,8 @@ pub fn func(stream: BoundaryStream, item: BoundaryStream) -> BoundaryStream {
|
||||
/// You can customize some properties of the resulting type:
|
||||
/// - `scope`: Indicates that the type has an associated scope defined by the
|
||||
/// `#[scope]` macro
|
||||
/// - `cast`: Indicates that the type has a custom `cast!` implementation.
|
||||
/// The macro will then not autogenerate one.
|
||||
/// - `name`: The type's normal name (e.g. `str`). Defaults to the Rust name in
|
||||
/// kebab-case.
|
||||
/// - `title`: The type's title case name (e.g. `String`). Defaults to the
|
||||
|
@ -28,18 +28,18 @@ pub fn ty(stream: TokenStream, item: syn::Item) -> Result<TokenStream> {
|
||||
|
||||
/// Holds all relevant parsed data about a type.
|
||||
struct Type {
|
||||
meta: Meta,
|
||||
ident: Ident,
|
||||
name: String,
|
||||
long: String,
|
||||
scope: bool,
|
||||
title: String,
|
||||
docs: String,
|
||||
keywords: Vec<String>,
|
||||
}
|
||||
|
||||
/// The `..` in `#[ty(..)]`.
|
||||
struct Meta {
|
||||
scope: bool,
|
||||
cast: bool,
|
||||
name: Option<String>,
|
||||
title: Option<String>,
|
||||
keywords: Vec<String>,
|
||||
@ -49,6 +49,7 @@ impl Parse for Meta {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
Ok(Self {
|
||||
scope: parse_flag::<kw::scope>(input)?,
|
||||
cast: parse_flag::<kw::cast>(input)?,
|
||||
name: parse_string::<kw::name>(input)?,
|
||||
title: parse_string::<kw::title>(input)?,
|
||||
keywords: parse_string_array::<kw::keywords>(input)?,
|
||||
@ -59,37 +60,35 @@ impl Parse for Meta {
|
||||
/// Parse details about the type from its definition.
|
||||
fn parse(meta: Meta, ident: Ident, attrs: &[Attribute]) -> Result<Type> {
|
||||
let docs = documentation(attrs);
|
||||
let (name, title) = determine_name_and_title(meta.name, meta.title, &ident, None)?;
|
||||
let (name, title) =
|
||||
determine_name_and_title(meta.name.clone(), meta.title.clone(), &ident, None)?;
|
||||
let long = title.to_lowercase();
|
||||
Ok(Type {
|
||||
ident,
|
||||
name,
|
||||
long,
|
||||
scope: meta.scope,
|
||||
keywords: meta.keywords,
|
||||
title,
|
||||
docs,
|
||||
})
|
||||
Ok(Type { meta, ident, name, long, title, docs })
|
||||
}
|
||||
|
||||
/// Produce the output of the macro.
|
||||
fn create(ty: &Type, item: Option<&syn::Item>) -> TokenStream {
|
||||
let Type {
|
||||
ident, name, long, title, docs, keywords, scope, ..
|
||||
} = ty;
|
||||
let Type { ident, name, long, title, docs, meta, .. } = ty;
|
||||
let Meta { keywords, .. } = meta;
|
||||
|
||||
let constructor = if *scope {
|
||||
let constructor = if meta.scope {
|
||||
quote! { <#ident as #foundations::NativeScope>::constructor() }
|
||||
} else {
|
||||
quote! { None }
|
||||
};
|
||||
|
||||
let scope = if *scope {
|
||||
let scope = if meta.scope {
|
||||
quote! { <#ident as #foundations::NativeScope>::scope() }
|
||||
} else {
|
||||
quote! { #foundations::Scope::new() }
|
||||
};
|
||||
|
||||
let cast = (!meta.cast).then(|| {
|
||||
quote! {
|
||||
#foundations::cast! { type #ident, }
|
||||
}
|
||||
});
|
||||
|
||||
let data = quote! {
|
||||
#foundations::NativeTypeData {
|
||||
name: #name,
|
||||
@ -104,6 +103,7 @@ fn create(ty: &Type, item: Option<&syn::Item>) -> TokenStream {
|
||||
|
||||
quote! {
|
||||
#item
|
||||
#cast
|
||||
|
||||
impl #foundations::NativeType for #ident {
|
||||
const NAME: &'static str = #name;
|
||||
|
@ -255,6 +255,7 @@ pub mod kw {
|
||||
syn::custom_keyword!(span);
|
||||
syn::custom_keyword!(title);
|
||||
syn::custom_keyword!(scope);
|
||||
syn::custom_keyword!(cast);
|
||||
syn::custom_keyword!(constructor);
|
||||
syn::custom_keyword!(keywords);
|
||||
syn::custom_keyword!(parent);
|
||||
|
@ -38,7 +38,7 @@ use crate::syntax::{Span, Spanned};
|
||||
/// #let dict = (fill: blue)
|
||||
/// #text(..dict)[Hello]
|
||||
/// ```
|
||||
#[ty(scope, name = "arguments")]
|
||||
#[ty(scope, cast, name = "arguments")]
|
||||
#[derive(Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Args {
|
||||
|
@ -67,7 +67,7 @@ pub use crate::__array as array;
|
||||
/// #(("A", "B", "C")
|
||||
/// .join(", ", last: " and "))
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Default, Clone, PartialEq, Hash, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Array(EcoVec<Value>);
|
||||
|
@ -15,7 +15,7 @@ use crate::foundations::{
|
||||
/// contextual behaviour. A good example is the [text direction]($text.dir)
|
||||
/// parameter. Setting it to `{auto}` lets Typst automatically determine the
|
||||
/// direction from the [text language]($text.lang).
|
||||
#[ty(name = "auto")]
|
||||
#[ty(cast, name = "auto")]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct AutoValue;
|
||||
|
||||
|
@ -13,7 +13,7 @@ use crate::foundations::{ty, Repr};
|
||||
/// #true \
|
||||
/// #(1 < 2)
|
||||
/// ```
|
||||
#[ty(title = "Boolean")]
|
||||
#[ty(cast, title = "Boolean")]
|
||||
type bool;
|
||||
|
||||
impl Repr for bool {
|
||||
|
@ -37,7 +37,7 @@ use crate::foundations::{cast, func, scope, ty, Array, Reflect, Repr, Str, Value
|
||||
/// #array(data.slice(0, 4)) \
|
||||
/// #str(data.slice(1, 4))
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Clone, Hash, Eq, PartialEq)]
|
||||
pub struct Bytes(Arc<Prehashed<Cow<'static, [u8]>>>);
|
||||
|
||||
|
@ -65,7 +65,7 @@ use crate::util::fat;
|
||||
/// In the web app, you can hover over a content variable to see exactly which
|
||||
/// elements the content is composed of and what fields they have.
|
||||
/// Alternatively, you can inspect the output of the [`repr`]($repr) function.
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Content(Arc<dyn NativeElement>);
|
||||
|
@ -111,7 +111,7 @@ use crate::World;
|
||||
/// will be stored as a plain date internally, meaning that you cannot use
|
||||
/// components such as `hour` or `minute`, which would only work on datetimes
|
||||
/// that have a specified time.
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Hash)]
|
||||
pub enum Datetime {
|
||||
/// Representation as a date.
|
||||
|
@ -62,7 +62,7 @@ pub use crate::__dict as dict;
|
||||
/// #dict.insert("city", "Berlin ")
|
||||
/// #("name" in dict)
|
||||
/// ```
|
||||
#[ty(scope, name = "dictionary")]
|
||||
#[ty(scope, cast, name = "dictionary")]
|
||||
#[derive(Default, Clone, PartialEq)]
|
||||
pub struct Dict(Arc<IndexMap<Str, Value>>);
|
||||
|
||||
|
@ -7,7 +7,7 @@ use time::ext::NumericalDuration;
|
||||
use crate::foundations::{func, repr, scope, ty, Repr};
|
||||
|
||||
/// Represents a positive or negative span of time.
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Duration(time::Duration);
|
||||
|
||||
|
@ -19,7 +19,7 @@ use crate::layout::Ratio;
|
||||
/// #1e4 \
|
||||
/// #(10 / 4)
|
||||
/// ```
|
||||
#[ty(scope, name = "float")]
|
||||
#[ty(scope, cast, name = "float")]
|
||||
type f64;
|
||||
|
||||
#[scope]
|
||||
|
@ -123,7 +123,7 @@ pub use typst_macros::func;
|
||||
/// The only exception are built-in methods like
|
||||
/// [`array.push(value)`]($array.push). These can modify the values they are
|
||||
/// called on.
|
||||
#[ty(scope, name = "function")]
|
||||
#[ty(scope, cast, name = "function")]
|
||||
#[derive(Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Func {
|
||||
|
@ -25,7 +25,7 @@ use crate::foundations::{cast, func, repr, scope, ty, Repr, Str, Value};
|
||||
/// #0o10 \
|
||||
/// #0b1001
|
||||
/// ```
|
||||
#[ty(scope, name = "int", title = "Integer")]
|
||||
#[ty(scope, cast, name = "int", title = "Integer")]
|
||||
type i64;
|
||||
|
||||
#[scope]
|
||||
|
@ -31,7 +31,7 @@ use crate::util::PicoStr;
|
||||
///
|
||||
/// Currently, labels can only be attached to elements in markup mode, not in
|
||||
/// code mode. This might change in the future.
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Label(PicoStr);
|
||||
|
||||
|
@ -23,7 +23,7 @@ use crate::foundations::{repr, ty, Content, Scope, Value};
|
||||
/// >>>
|
||||
/// >>> #(-3)
|
||||
/// ```
|
||||
#[ty]
|
||||
#[ty(cast)]
|
||||
#[derive(Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Module {
|
||||
|
@ -20,7 +20,7 @@ use crate::foundations::{
|
||||
/// ```example
|
||||
/// Not visible: #none
|
||||
/// ```
|
||||
#[ty(name = "none")]
|
||||
#[ty(cast, name = "none")]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct NoneValue;
|
||||
|
||||
|
@ -115,7 +115,7 @@ use crate::World;
|
||||
/// - Wrappers to help you write your plugin in Rust (Zig wrapper in
|
||||
/// development)
|
||||
/// - A stubber for WASI
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Clone)]
|
||||
pub struct Plugin(Arc<Repr>);
|
||||
|
||||
|
@ -76,7 +76,7 @@ pub use crate::__select_where as select_where;
|
||||
/// == So will this
|
||||
/// === But this will not.
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub enum Selector {
|
||||
/// Matches a specific type of element.
|
||||
|
@ -67,7 +67,7 @@ pub use ecow::eco_format;
|
||||
/// - `[\r]` for a carriage return
|
||||
/// - `[\t]` for a tab
|
||||
/// - `[\u{1f600}]` for a hexadecimal Unicode escape sequence
|
||||
#[ty(scope, title = "String")]
|
||||
#[ty(scope, cast, title = "String")]
|
||||
#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
@ -898,10 +898,6 @@ impl Hash for Regex {
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
type Regex,
|
||||
}
|
||||
|
||||
/// A pattern which can be searched for in a string.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum StrPattern {
|
||||
|
@ -64,7 +64,7 @@ impl Show for StyleElem {
|
||||
}
|
||||
|
||||
/// A list of style properties.
|
||||
#[ty]
|
||||
#[ty(cast)]
|
||||
#[derive(Default, PartialEq, Clone, Hash)]
|
||||
pub struct Styles(EcoVec<Prehashed<Style>>);
|
||||
|
||||
|
@ -53,7 +53,7 @@ pub use typst_macros::{scope, ty};
|
||||
/// - Adding/joining a type and string will yield a string
|
||||
/// - The `{in}` operator on a type and a dictionary will evaluate to `{true}`
|
||||
/// if the dictionary has a string key matching the type's name
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Type(Static<NativeTypeData>);
|
||||
|
||||
|
@ -20,7 +20,7 @@ use crate::foundations::{cast, func, repr, scope, ty, Repr};
|
||||
///
|
||||
/// You can convert a version to an array of explicitly given components using
|
||||
/// the [`array`]($array) constructor.
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Debug, Default, Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Version(EcoVec<u32>);
|
||||
|
@ -475,10 +475,6 @@ impl Repr for Counter {
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
type Counter,
|
||||
}
|
||||
|
||||
/// Identifies a counter.
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub enum CounterKey {
|
||||
@ -521,7 +517,7 @@ impl Repr for CounterKey {
|
||||
}
|
||||
|
||||
/// An update to perform on a counter.
|
||||
#[ty]
|
||||
#[ty(cast)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub enum CounterUpdate {
|
||||
/// Set the counter to the specified state.
|
||||
|
@ -3,7 +3,7 @@ use std::num::NonZeroUsize;
|
||||
use ecow::EcoString;
|
||||
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{cast, func, scope, ty, Dict, Repr};
|
||||
use crate::foundations::{func, scope, ty, Dict, Repr};
|
||||
use crate::model::Numbering;
|
||||
|
||||
/// Identifies an element in the document.
|
||||
@ -79,9 +79,5 @@ impl Repr for Location {
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
type Location,
|
||||
}
|
||||
|
||||
/// Makes this element locatable through `engine.locate`.
|
||||
pub trait Locatable {}
|
||||
|
@ -26,8 +26,7 @@ use ecow::{eco_format, EcoString};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::foundations::{
|
||||
cast, category, elem, ty, Behave, Behaviour, Category, Content, Repr, Scope,
|
||||
Unlabellable,
|
||||
category, elem, ty, Behave, Behaviour, Category, Content, Repr, Scope, Unlabellable,
|
||||
};
|
||||
use crate::layout::PdfPageLabel;
|
||||
use crate::model::{Destination, Numbering};
|
||||
@ -89,10 +88,6 @@ pub enum Meta {
|
||||
Hide,
|
||||
}
|
||||
|
||||
cast! {
|
||||
type Meta,
|
||||
}
|
||||
|
||||
impl Debug for Meta {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
|
@ -351,12 +351,8 @@ impl Repr for State {
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
type State,
|
||||
}
|
||||
|
||||
/// An update to perform on a state.
|
||||
#[ty]
|
||||
#[ty(cast)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub enum StateUpdate {
|
||||
/// Set the state to the specified value.
|
||||
|
@ -245,10 +245,6 @@ impl From<Side> for Alignment {
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
type Alignment,
|
||||
}
|
||||
|
||||
/// Where to align something horizontally.
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum HAlignment {
|
||||
|
@ -19,7 +19,7 @@ use crate::util::{Numeric, Scalar};
|
||||
/// ```example
|
||||
/// #rotate(10deg)[Hello there!]
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Angle(Scalar);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use ecow::EcoString;
|
||||
|
||||
use crate::foundations::{cast, func, scope, ty, Repr};
|
||||
use crate::foundations::{func, scope, ty, Repr};
|
||||
use crate::layout::{Axis, Side};
|
||||
|
||||
/// The four directions into which content can be laid out.
|
||||
@ -130,7 +130,3 @@ impl Repr for Dir {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
type Dir,
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ use crate::util::{Numeric, Scalar};
|
||||
/// ```example
|
||||
/// Left #h(1fr) Left-ish #h(2fr) Right
|
||||
/// ```
|
||||
#[ty(name = "fraction")]
|
||||
#[ty(cast, name = "fraction")]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Fr(Scalar);
|
||||
|
||||
|
@ -38,7 +38,7 @@ use crate::util::Numeric;
|
||||
/// - `abs`: A length with just the absolute component of the current length
|
||||
/// (that is, excluding the `em` component).
|
||||
/// - `em`: The amount of `em` units in this length, as a [float]($float).
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Length {
|
||||
/// The absolute part.
|
||||
|
@ -17,7 +17,7 @@ use crate::util::{Numeric, Scalar};
|
||||
/// Scaled apart.
|
||||
/// ]
|
||||
/// ```
|
||||
#[ty]
|
||||
#[ty(cast)]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Ratio(Scalar);
|
||||
|
||||
|
@ -25,7 +25,7 @@ use crate::util::Numeric;
|
||||
/// A relative length has the following fields:
|
||||
/// - `length`: Its length component.
|
||||
/// - `ratio`: Its ratio component.
|
||||
#[ty(name = "relative", title = "Relative Length")]
|
||||
#[ty(cast, name = "relative", title = "Relative Length")]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Rel<T: Numeric = Length> {
|
||||
/// The relative part.
|
||||
|
@ -421,10 +421,6 @@ impl Repr for Bibliography {
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
type Bibliography,
|
||||
}
|
||||
|
||||
/// Format a BibLaTeX loading error.
|
||||
fn format_biblatex_error(path: &str, src: &str, errors: Vec<BibLaTeXError>) -> EcoString {
|
||||
let Some(error) = errors.first() else {
|
||||
@ -440,7 +436,7 @@ fn format_biblatex_error(path: &str, src: &str, errors: Vec<BibLaTeXError>) -> E
|
||||
}
|
||||
|
||||
/// A loaded CSL style.
|
||||
#[ty]
|
||||
#[ty(cast)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub struct CslStyle {
|
||||
name: Option<EcoString>,
|
||||
|
@ -42,7 +42,7 @@ pub use typst_macros::symbols;
|
||||
/// $arrow.r$ \
|
||||
/// $arrow.t.quad$
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Symbol(Repr);
|
||||
|
||||
|
@ -5,7 +5,7 @@ use ecow::{eco_format, EcoString};
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{cast, elem, ty, Content, Fold, Repr, Show, Smart, StyleChain};
|
||||
use crate::foundations::{elem, ty, Content, Fold, Repr, Show, Smart, StyleChain};
|
||||
use crate::layout::{Abs, Em, Frame, FrameItem, Length, Point, Size};
|
||||
use crate::syntax::Span;
|
||||
use crate::text::{
|
||||
@ -363,10 +363,6 @@ impl Repr for Decoration {
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
type Decoration,
|
||||
}
|
||||
|
||||
/// A kind of decorative line.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
enum DecoLine {
|
||||
|
@ -163,7 +163,7 @@ const ANGLE_EPSILON: f32 = 1e-5;
|
||||
/// )
|
||||
/// }))
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Color {
|
||||
/// A 32-bit luma color.
|
||||
|
@ -175,7 +175,7 @@ use crate::visualize::{Color, ColorSpace, WeightedColor};
|
||||
/// [`color.oklab`]($color.oklab) colors with extra stops in between. This
|
||||
/// avoids needing to encode these color spaces in your PDF file, but it does
|
||||
/// add extra stops to your gradient, which can increase the file size.
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Gradient {
|
||||
Linear(Arc<LinearGradient>),
|
||||
|
@ -95,7 +95,7 @@ use crate::World;
|
||||
/// that are implicitly created by show rules and elements. For example, a
|
||||
/// [`rotate`]($rotate) will not affect the parent of a gradient, but a
|
||||
/// [`grid`]($grid) will.
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Pattern(Arc<Repr>);
|
||||
|
||||
|
@ -49,7 +49,7 @@ use crate::visualize::{Color, Gradient, Paint, Pattern};
|
||||
/// constructor function. For example, `{(2pt + blue).thickness}` is `{2pt}`.
|
||||
/// Meanwhile, `{stroke(red).cap}` is `{auto}` because it's unspecified. Fields
|
||||
/// set to `{auto}` are inherited.
|
||||
#[ty(scope)]
|
||||
#[ty(scope, cast)]
|
||||
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Stroke<T: Numeric = Length> {
|
||||
/// The stroke's paint.
|
||||
|
Loading…
x
Reference in New Issue
Block a user