From c309221bfe534bc0b734206c76797e4930b2a4f5 Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 20:04:05 +0400 Subject: [PATCH 01/17] add gen-api-shorthands crate --- Cargo.lock | 24 ++++++++ Cargo.toml | 5 ++ support/bindgen/Cargo.toml | 6 +- support/gen-api-shorthands/Cargo.toml | 19 ++++++ support/gen-api-shorthands/src/lib.rs | 85 +++++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 support/gen-api-shorthands/Cargo.toml create mode 100644 support/gen-api-shorthands/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 0880c973..ce2d9456 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1243,6 +1243,17 @@ dependencies = [ "serde", ] +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "derive_arbitrary" version = "1.4.1" @@ -4191,6 +4202,7 @@ name = "playdate-controls" version = "0.3.8" dependencies = [ "playdate-display", + "playdate-gen-api-shorthands", "playdate-graphics", "playdate-sys", "playdate-system", @@ -4230,6 +4242,7 @@ dependencies = [ name = "playdate-display" version = "0.3.8" dependencies = [ + "playdate-gen-api-shorthands", "playdate-sys", ] @@ -4241,6 +4254,16 @@ dependencies = [ "playdate-system", ] +[[package]] +name = "playdate-gen-api-shorthands" +version = "0.1.0" +dependencies = [ + "derive-syn-parse", + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "playdate-graphics" version = "0.4.3" @@ -4343,6 +4366,7 @@ dependencies = [ name = "playdate-system" version = "0.3.15" dependencies = [ + "playdate-gen-api-shorthands", "playdate-sys", ] diff --git a/Cargo.toml b/Cargo.toml index 4dea0826..76b59b07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ device = { version = "0.2", path = "support/device", package = "playdate-device" simulator = { version = "0.1", path = "support/sim-ctrl", package = "playdate-simulator-utils", default-features = false } bindgen = { version = "0.2", path = "support/bindgen", package = "playdate-bindgen", default-features = false } bindgen-cfg = { version = "0.2", path = "support/bindgen-cfg", package = "playdate-bindgen-cfg", default-features = false } +gen-api-shorthands = { version = "0.1", path = "support/gen-api-shorthands", package = "playdate-gen-api-shorthands" } # Deps that used multiple times, # This is to prevent various versions in the deps-tree for faster compilation time @@ -52,6 +53,10 @@ thiserror = "2.0" tokio = { version = "1.43", default-features = false } async-std = { version = "1.13", default-features = false } +proc-macro2 = { version = "1.0" } +quote = { version = "1.0" } +syn = { version = "2.0", features = ["extra-traits", "full", "parsing"] } + [workspace.metadata.playdate.options.assets] dependencies = true diff --git a/support/bindgen/Cargo.toml b/support/bindgen/Cargo.toml index d3110b32..6fa7c653 100644 --- a/support/bindgen/Cargo.toml +++ b/support/bindgen/Cargo.toml @@ -21,9 +21,9 @@ html5ever = { version = "0.27.0", optional = true } markup5ever_rcdom = { version = "0.3.0", optional = true } # doc-gen: -proc-macro2 = { version = "1.0", optional = true } -syn = { version = "2.0", optional = true } # +full, extra-traits, visit-mut -quote = { version = "1.0", optional = true } +proc-macro2 = { workspace = true, optional = true } +quote = { workspace = true, optional = true } +syn = { workspace = true, optional = true } log = { workspace = true, optional = true } prettyplease = { version = "0.2", optional = true, features = ["verbatim"] } diff --git a/support/gen-api-shorthands/Cargo.toml b/support/gen-api-shorthands/Cargo.toml new file mode 100644 index 00000000..2e25a5bb --- /dev/null +++ b/support/gen-api-shorthands/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "playdate-gen-api-shorthands" +version = "0.1.0" +keywords = ["playdate", "bindings", "code-generation"] +categories = ["development-tools::ffi", "development-tools::build-utils"] +edition.workspace = true +license.workspace = true +authors.workspace = ["kana "] +homepage.workspace = true +repository.workspace = true + +[lib] +proc-macro = true + +[dependencies] +derive-syn-parse = "0.2.0" +proc-macro2.workspace = true +quote.workspace = true +syn.workspace = true diff --git a/support/gen-api-shorthands/src/lib.rs b/support/gen-api-shorthands/src/lib.rs new file mode 100644 index 00000000..a039ed44 --- /dev/null +++ b/support/gen-api-shorthands/src/lib.rs @@ -0,0 +1,85 @@ +#![feature(assert_matches)] +#![feature(proc_macro_expand)] + +use std::assert_matches::assert_matches; + +use derive_syn_parse::Parse; +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, FnArg, Ident, ImplItem, ImplItemFn, ItemImpl, Signature, Token, Visibility}; + +#[derive(Parse)] +struct AttrValue { + mod_vis: Visibility, + mod_token: Token![mod], + mod_name: Ident, +} + +#[proc_macro_attribute] +pub fn gen_shorthands_mod(attr: TokenStream, item: TokenStream) -> TokenStream { + let source_impl: proc_macro2::TokenStream = item.clone().into(); + + let AttrValue { mod_vis, mod_token, mod_name } = parse_macro_input!(attr as AttrValue); + let ItemImpl { trait_, items, self_ty, .. } = parse_macro_input!(item as ItemImpl); + + let self_ty = match *self_ty { + syn::Type::Path(syn::TypePath { qself: None, path }) => path + .segments.last().expect("empty path") + .ident.clone(), + _ => panic!("only simple paths are supported"), + }; + + assert!(trait_.is_none(), "trait impls are not supported"); + + let shorthands = items.into_iter().map(|item| { + let ImplItem::Fn(ImplItemFn { attrs, defaultness, sig, vis: _, block: _ }) = item else { + panic!("only methods are supported"); + }; + + let Signature { constness, asyncness, unsafety, abi, fn_token: _, ident, generics, paren_token: _, inputs, variadic, output } = sig; + let where_clause = &generics.where_clause; + + assert!(defaultness.is_none(), "default methods are not supported"); + assert!(constness.is_none(), "const methods are not supported"); + assert!(asyncness.is_none(), "async methods are not supported"); + assert!(unsafety.is_none(), "unsafe methods are not supported"); + assert!(abi.is_none(), "extern methods are not supported"); + assert!(variadic.is_none(), "variadic methods are not supported"); + + assert_matches!(inputs.first(), Some(FnArg::Receiver(_)), "only methods are supported"); + + let inputs = inputs.iter() + .filter_map(|input| match input { + FnArg::Receiver(_) => None, + FnArg::Typed(arg) => Some(arg), + }) + .collect::>(); + + let inputs_args = inputs.iter() + .map(|pat| &pat.pat) + .collect::>(); + + let shorthand_doc = quote! { concat!(" This function is shorthand for [`", stringify!(#self_ty), "::", stringify!(#ident), "`], using default ZST end-point.") }; + let shorthand_doc: proc_macro2::TokenStream = TokenStream::from(shorthand_doc).expand_expr().unwrap().into(); + + quote! { + #(#attrs)* + #[doc = ""] + #[doc = #shorthand_doc] + #[inline(always)] + pub fn #ident #generics ( #(#inputs),* ) #output #where_clause { + #self_ty::Default().#ident( #(#inputs_args),* ) + } + } + }).collect::>(); + + TokenStream::from(quote! { + #source_impl + + #mod_vis #mod_token #mod_name { + use super::*; + + #(#shorthands)* + } + }) +} From 1885a2e696be6acc375db4e07c3d650786bd25d7 Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 20:05:17 +0400 Subject: [PATCH 02/17] use gen-api-shorthands in playdate-display --- api/display/Cargo.toml | 8 +++----- api/display/src/lib.rs | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/api/display/Cargo.toml b/api/display/Cargo.toml index bb7e1e98..c4a5889a 100644 --- a/api/display/Cargo.toml +++ b/api/display/Cargo.toml @@ -21,11 +21,9 @@ bindgen-runtime = ["sys/bindgen-runtime"] bindgen-static = ["sys/bindgen-static"] bindings-derive-debug = ["sys/bindings-derive-debug"] - -[dependencies.sys] -workspace = true -default-features = false - +[dependencies] +gen-api-shorthands.workspace = true +sys = { workspace = true, default-features = false } [package.metadata.docs.rs] all-features = false diff --git a/api/display/src/lib.rs b/api/display/src/lib.rs index 5c7c5406..847b2038 100644 --- a/api/display/src/lib.rs +++ b/api/display/src/lib.rs @@ -5,7 +5,6 @@ use core::ffi::c_float; use core::ffi::c_int; use core::ffi::c_uint; - #[derive(Debug, Clone, Copy)] pub struct Display(Api); @@ -48,7 +47,8 @@ impl Display { bottom: Self::ROWS as _ }; } - +pub use shorthands::*; +#[gen_api_shorthands::gen_shorthands_mod(mod shorthands)] impl Display { /// Returns the width of the display, taking the current scale into account; /// From 2011a1738f8d1862bfc34f62ea48a4eee65b7017 Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 20:05:32 +0400 Subject: [PATCH 03/17] use gen-api-shorthands in playdate-controls --- api/ctrl/Cargo.toml | 1 + api/ctrl/src/buttons.rs | 1 + api/ctrl/src/lib.rs | 8 ++++++++ api/ctrl/src/peripherals.rs | 5 +++++ 4 files changed, 15 insertions(+) diff --git a/api/ctrl/Cargo.toml b/api/ctrl/Cargo.toml index a09737b9..357bce92 100644 --- a/api/ctrl/Cargo.toml +++ b/api/ctrl/Cargo.toml @@ -23,6 +23,7 @@ bindings-derive-debug = ["sys/bindings-derive-debug"] [dependencies] +gen-api-shorthands.workspace = true sys = { workspace = true, default-features = false } system = { workspace = true, default-features = false } diff --git a/api/ctrl/src/buttons.rs b/api/ctrl/src/buttons.rs index 1655bf36..5eb23118 100644 --- a/api/ctrl/src/buttons.rs +++ b/api/ctrl/src/buttons.rs @@ -3,6 +3,7 @@ use core::fmt::Display; use core::ops::BitAnd; use sys::ffi::PDButtons; +pub use crate::peripherals::buttons_shorthands::*; pub trait PDButtonsExt: Sized + BitAnd { #![allow(non_snake_case)] diff --git a/api/ctrl/src/lib.rs b/api/ctrl/src/lib.rs index 4fe5b87c..a1f120c6 100644 --- a/api/ctrl/src/lib.rs +++ b/api/ctrl/src/lib.rs @@ -10,3 +10,11 @@ extern crate sys; pub mod api; pub mod buttons; pub mod peripherals; + +pub mod accelerometer { + pub use crate::peripherals::accelerometer_shorthands::*; +} + +pub mod crank { + pub use crate::peripherals::crank_shorthands::*; +} diff --git a/api/ctrl/src/peripherals.rs b/api/ctrl/src/peripherals.rs index 38a7c44d..9123f2a5 100644 --- a/api/ctrl/src/peripherals.rs +++ b/api/ctrl/src/peripherals.rs @@ -42,6 +42,8 @@ impl Peripherals where Api: Copy { pub const fn crank(&self) -> Crank { Crank(self.0) } } +pub use shorthands::*; +#[gen_api_shorthands::gen_shorthands_mod(mod shorthands)] impl Peripherals { /// Enables specified peripheral. /// @@ -134,6 +136,7 @@ impl Accelerometer { pub const fn new_with(api: Api) -> Self { Self(api) } } +#[gen_api_shorthands::gen_shorthands_mod(pub(crate) mod accelerometer_shorthands)] impl Accelerometer { /// Enables accelerometer only. /// @@ -218,6 +221,7 @@ impl Buttons { pub const fn new_with(api: Api) -> Self { Self(api) } } +#[gen_api_shorthands::gen_shorthands_mod(pub(crate) mod buttons_shorthands)] impl Buttons { /// Returns the current buttons [`State`]. /// @@ -363,6 +367,7 @@ impl Crank { pub const fn new_with(api: Api) -> Self { Self(api) } } +#[gen_api_shorthands::gen_shorthands_mod(pub(crate) mod crank_shorthands)] impl Crank { /// Returns boolean indicating whether or not the crank is folded into the unit. /// From 4b341c154c074cf68d74a45ed8f01b22a87e39ce Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 20:05:38 +0400 Subject: [PATCH 04/17] use gen-api-shorthands in playdate-system --- api/system/Cargo.toml | 8 +++----- api/system/src/lib.rs | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/api/system/Cargo.toml b/api/system/Cargo.toml index 2282fd6a..806bd766 100644 --- a/api/system/Cargo.toml +++ b/api/system/Cargo.toml @@ -22,11 +22,9 @@ bindgen-runtime = ["sys/bindgen-runtime"] bindgen-static = ["sys/bindgen-static"] bindings-derive-debug = ["sys/bindings-derive-debug"] - -[dependencies.sys] -workspace = true -default-features = false - +[dependencies] +gen-api-shorthands.workspace = true +sys = { workspace = true, default-features = false } [[example]] name = "handler-boxed" diff --git a/api/system/src/lib.rs b/api/system/src/lib.rs index c6c662d2..b185cd8f 100644 --- a/api/system/src/lib.rs +++ b/api/system/src/lib.rs @@ -65,7 +65,8 @@ impl System { } } - +pub use shorthands::*; +#[gen_api_shorthands::gen_shorthands_mod(mod shorthands)] impl System { /// Equivalent to [`sys::ffi::playdate_sys::getLanguage`] #[doc(alias = "sys::ffi::playdate_sys::getLanguage")] From fa5a7083e5d0804f156e47c287b193cdc3bc1c27 Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 20:13:48 +0400 Subject: [PATCH 05/17] playdate-gen-api-shorthands authors --- support/gen-api-shorthands/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/gen-api-shorthands/Cargo.toml b/support/gen-api-shorthands/Cargo.toml index 2e25a5bb..299a916d 100644 --- a/support/gen-api-shorthands/Cargo.toml +++ b/support/gen-api-shorthands/Cargo.toml @@ -5,7 +5,7 @@ keywords = ["playdate", "bindings", "code-generation"] categories = ["development-tools::ffi", "development-tools::build-utils"] edition.workspace = true license.workspace = true -authors.workspace = ["kana "] +authors = ["kana "] homepage.workspace = true repository.workspace = true From 3e67cd3ffbcccde3e0fa81ac14f54d4697cac403 Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 20:19:58 +0400 Subject: [PATCH 06/17] fix indentaion --- api/ctrl/src/lib.rs | 4 +- support/gen-api-shorthands/src/lib.rs | 136 +++++++++++++------------- 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/api/ctrl/src/lib.rs b/api/ctrl/src/lib.rs index a1f120c6..1dff3829 100644 --- a/api/ctrl/src/lib.rs +++ b/api/ctrl/src/lib.rs @@ -12,9 +12,9 @@ pub mod buttons; pub mod peripherals; pub mod accelerometer { - pub use crate::peripherals::accelerometer_shorthands::*; + pub use crate::peripherals::accelerometer_shorthands::*; } pub mod crank { - pub use crate::peripherals::crank_shorthands::*; + pub use crate::peripherals::crank_shorthands::*; } diff --git a/support/gen-api-shorthands/src/lib.rs b/support/gen-api-shorthands/src/lib.rs index a039ed44..983f6385 100644 --- a/support/gen-api-shorthands/src/lib.rs +++ b/support/gen-api-shorthands/src/lib.rs @@ -10,76 +10,76 @@ use syn::{parse_macro_input, FnArg, Ident, ImplItem, ImplItemFn, ItemImpl, Signa #[derive(Parse)] struct AttrValue { - mod_vis: Visibility, - mod_token: Token![mod], - mod_name: Ident, + mod_vis: Visibility, + mod_token: Token![mod], + mod_name: Ident, } #[proc_macro_attribute] pub fn gen_shorthands_mod(attr: TokenStream, item: TokenStream) -> TokenStream { - let source_impl: proc_macro2::TokenStream = item.clone().into(); - - let AttrValue { mod_vis, mod_token, mod_name } = parse_macro_input!(attr as AttrValue); - let ItemImpl { trait_, items, self_ty, .. } = parse_macro_input!(item as ItemImpl); - - let self_ty = match *self_ty { - syn::Type::Path(syn::TypePath { qself: None, path }) => path - .segments.last().expect("empty path") - .ident.clone(), - _ => panic!("only simple paths are supported"), - }; - - assert!(trait_.is_none(), "trait impls are not supported"); - - let shorthands = items.into_iter().map(|item| { - let ImplItem::Fn(ImplItemFn { attrs, defaultness, sig, vis: _, block: _ }) = item else { - panic!("only methods are supported"); - }; - - let Signature { constness, asyncness, unsafety, abi, fn_token: _, ident, generics, paren_token: _, inputs, variadic, output } = sig; - let where_clause = &generics.where_clause; - - assert!(defaultness.is_none(), "default methods are not supported"); - assert!(constness.is_none(), "const methods are not supported"); - assert!(asyncness.is_none(), "async methods are not supported"); - assert!(unsafety.is_none(), "unsafe methods are not supported"); - assert!(abi.is_none(), "extern methods are not supported"); - assert!(variadic.is_none(), "variadic methods are not supported"); - - assert_matches!(inputs.first(), Some(FnArg::Receiver(_)), "only methods are supported"); - - let inputs = inputs.iter() - .filter_map(|input| match input { - FnArg::Receiver(_) => None, - FnArg::Typed(arg) => Some(arg), - }) - .collect::>(); - - let inputs_args = inputs.iter() - .map(|pat| &pat.pat) - .collect::>(); - - let shorthand_doc = quote! { concat!(" This function is shorthand for [`", stringify!(#self_ty), "::", stringify!(#ident), "`], using default ZST end-point.") }; - let shorthand_doc: proc_macro2::TokenStream = TokenStream::from(shorthand_doc).expand_expr().unwrap().into(); - - quote! { - #(#attrs)* - #[doc = ""] - #[doc = #shorthand_doc] - #[inline(always)] - pub fn #ident #generics ( #(#inputs),* ) #output #where_clause { - #self_ty::Default().#ident( #(#inputs_args),* ) - } - } - }).collect::>(); - - TokenStream::from(quote! { - #source_impl - - #mod_vis #mod_token #mod_name { - use super::*; - - #(#shorthands)* - } - }) + let source_impl: proc_macro2::TokenStream = item.clone().into(); + + let AttrValue { mod_vis, mod_token, mod_name } = parse_macro_input!(attr as AttrValue); + let ItemImpl { trait_, items, self_ty, .. } = parse_macro_input!(item as ItemImpl); + + let self_ty = match *self_ty { + syn::Type::Path(syn::TypePath { qself: None, path }) => path + .segments.last().expect("empty path") + .ident.clone(), + _ => panic!("only simple paths are supported"), + }; + + assert!(trait_.is_none(), "trait impls are not supported"); + + let shorthands = items.into_iter().map(|item| { + let ImplItem::Fn(ImplItemFn { attrs, defaultness, sig, vis: _, block: _ }) = item else { + panic!("only methods are supported"); + }; + + let Signature { constness, asyncness, unsafety, abi, fn_token: _, ident, generics, paren_token: _, inputs, variadic, output } = sig; + let where_clause = &generics.where_clause; + + assert!(defaultness.is_none(), "default methods are not supported"); + assert!(constness.is_none(), "const methods are not supported"); + assert!(asyncness.is_none(), "async methods are not supported"); + assert!(unsafety.is_none(), "unsafe methods are not supported"); + assert!(abi.is_none(), "extern methods are not supported"); + assert!(variadic.is_none(), "variadic methods are not supported"); + + assert_matches!(inputs.first(), Some(FnArg::Receiver(_)), "only methods are supported"); + + let inputs = inputs.iter() + .filter_map(|input| match input { + FnArg::Receiver(_) => None, + FnArg::Typed(arg) => Some(arg), + }) + .collect::>(); + + let inputs_args = inputs.iter() + .map(|pat| &pat.pat) + .collect::>(); + + let shorthand_doc = quote! { concat!(" This function is shorthand for [`", stringify!(#self_ty), "::", stringify!(#ident), "`], using default ZST end-point.") }; + let shorthand_doc: proc_macro2::TokenStream = TokenStream::from(shorthand_doc).expand_expr().unwrap().into(); + + quote! { + #(#attrs)* + #[doc = ""] + #[doc = #shorthand_doc] + #[inline(always)] + pub fn #ident #generics ( #(#inputs),* ) #output #where_clause { + #self_ty::Default().#ident( #(#inputs_args),* ) + } + } + }).collect::>(); + + TokenStream::from(quote! { + #source_impl + + #mod_vis #mod_token #mod_name { + use super::*; + + #(#shorthands)* + } + }) } From b994c20420cfe03b50476885e0819c15c51803fd Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 20:52:34 +0400 Subject: [PATCH 07/17] gen-api-shorthands: make mod optional --- api/ctrl/src/peripherals.rs | 9 ++++----- api/display/src/lib.rs | 3 +-- api/system/src/lib.rs | 3 +-- support/gen-api-shorthands/src/lib.rs | 25 ++++++++++++++++--------- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/api/ctrl/src/peripherals.rs b/api/ctrl/src/peripherals.rs index 9123f2a5..f8869167 100644 --- a/api/ctrl/src/peripherals.rs +++ b/api/ctrl/src/peripherals.rs @@ -42,8 +42,7 @@ impl Peripherals where Api: Copy { pub const fn crank(&self) -> Crank { Crank(self.0) } } -pub use shorthands::*; -#[gen_api_shorthands::gen_shorthands_mod(mod shorthands)] +#[gen_api_shorthands::gen_shorthands] impl Peripherals { /// Enables specified peripheral. /// @@ -136,7 +135,7 @@ impl Accelerometer { pub const fn new_with(api: Api) -> Self { Self(api) } } -#[gen_api_shorthands::gen_shorthands_mod(pub(crate) mod accelerometer_shorthands)] +#[gen_api_shorthands::gen_shorthands(pub(crate) mod accelerometer_shorthands)] impl Accelerometer { /// Enables accelerometer only. /// @@ -221,7 +220,7 @@ impl Buttons { pub const fn new_with(api: Api) -> Self { Self(api) } } -#[gen_api_shorthands::gen_shorthands_mod(pub(crate) mod buttons_shorthands)] +#[gen_api_shorthands::gen_shorthands(pub(crate) mod buttons_shorthands)] impl Buttons { /// Returns the current buttons [`State`]. /// @@ -367,7 +366,7 @@ impl Crank { pub const fn new_with(api: Api) -> Self { Self(api) } } -#[gen_api_shorthands::gen_shorthands_mod(pub(crate) mod crank_shorthands)] +#[gen_api_shorthands::gen_shorthands(pub(crate) mod crank_shorthands)] impl Crank { /// Returns boolean indicating whether or not the crank is folded into the unit. /// diff --git a/api/display/src/lib.rs b/api/display/src/lib.rs index 847b2038..9a93d545 100644 --- a/api/display/src/lib.rs +++ b/api/display/src/lib.rs @@ -47,8 +47,7 @@ impl Display { bottom: Self::ROWS as _ }; } -pub use shorthands::*; -#[gen_api_shorthands::gen_shorthands_mod(mod shorthands)] +#[gen_api_shorthands::gen_shorthands] impl Display { /// Returns the width of the display, taking the current scale into account; /// diff --git a/api/system/src/lib.rs b/api/system/src/lib.rs index b185cd8f..901489ef 100644 --- a/api/system/src/lib.rs +++ b/api/system/src/lib.rs @@ -65,8 +65,7 @@ impl System { } } -pub use shorthands::*; -#[gen_api_shorthands::gen_shorthands_mod(mod shorthands)] +#[gen_api_shorthands::gen_shorthands] impl System { /// Equivalent to [`sys::ffi::playdate_sys::getLanguage`] #[doc(alias = "sys::ffi::playdate_sys::getLanguage")] diff --git a/support/gen-api-shorthands/src/lib.rs b/support/gen-api-shorthands/src/lib.rs index 983f6385..bd3433ea 100644 --- a/support/gen-api-shorthands/src/lib.rs +++ b/support/gen-api-shorthands/src/lib.rs @@ -16,10 +16,8 @@ struct AttrValue { } #[proc_macro_attribute] -pub fn gen_shorthands_mod(attr: TokenStream, item: TokenStream) -> TokenStream { +pub fn gen_shorthands(attr: TokenStream, item: TokenStream) -> TokenStream { let source_impl: proc_macro2::TokenStream = item.clone().into(); - - let AttrValue { mod_vis, mod_token, mod_name } = parse_macro_input!(attr as AttrValue); let ItemImpl { trait_, items, self_ty, .. } = parse_macro_input!(item as ItemImpl); let self_ty = match *self_ty { @@ -73,13 +71,22 @@ pub fn gen_shorthands_mod(attr: TokenStream, item: TokenStream) -> TokenStream { } }).collect::>(); - TokenStream::from(quote! { - #source_impl + let mut shorthands = quote! { #(#shorthands)* }; - #mod_vis #mod_token #mod_name { - use super::*; + if !attr.is_empty() { + let AttrValue { mod_vis, mod_token, mod_name } = parse_macro_input!(attr as AttrValue); - #(#shorthands)* - } + shorthands = quote! { + #mod_vis #mod_token #mod_name { + use super::*; + + #shorthands + } + }; + } + + TokenStream::from(quote! { + #source_impl + #shorthands }) } From 516cfcdafc33486cc602e6e2ed4400bf2f06a5f2 Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 20:58:49 +0400 Subject: [PATCH 08/17] use gen-api-shorthands in playdate-graphics --- Cargo.lock | 1 + api/gfx/Cargo.toml | 1 + api/gfx/src/lib.rs | 268 +-------------------------------------------- 3 files changed, 3 insertions(+), 267 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce2d9456..195610f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4271,6 +4271,7 @@ dependencies = [ "playdate-color", "playdate-display", "playdate-fs", + "playdate-gen-api-shorthands", "playdate-sys", "playdate-system", ] diff --git a/api/gfx/Cargo.toml b/api/gfx/Cargo.toml index b2728584..da2a599e 100644 --- a/api/gfx/Cargo.toml +++ b/api/gfx/Cargo.toml @@ -24,6 +24,7 @@ bindings-derive-debug = ["sys/bindings-derive-debug", "color/bindings-derive-deb [dependencies] +gen-api-shorthands.workspace = true sys = { workspace = true, default-features = false } fs = { workspace = true, default-features = false } color = { workspace = true, default-features = false } diff --git a/api/gfx/src/lib.rs b/api/gfx/src/lib.rs index b44e1366..58afc1df 100644 --- a/api/gfx/src/lib.rs +++ b/api/gfx/src/lib.rs @@ -52,273 +52,6 @@ unsafe fn as_slice_mut(buf: *mut u8) -> Result<&'static mut [u8], ApiError> { } -/// Returns the current display frame buffer. -/// Rows are 32-bit aligned, so the row stride is 52 bytes, with the extra 2 bytes per row ignored. -/// Bytes are MSB-ordered; i.e., the pixel in column 0 is the 0x80 bit of the first byte of the row. -/// -/// This function is shorthand for [`Graphics::get_frame`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getFrame`]. -#[doc(alias = "sys::ffi::playdate_graphics::getFrame")] -#[inline(always)] -pub fn get_frame() -> Result<&'static mut [u8], ApiError> { Graphics::Default().get_frame() } - - -/// Returns the raw bits in the display buffer, -/// __the last completed frame__. -/// -/// This function is shorthand for [`Graphics::get_display_frame`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getDisplayFrame`]. -#[doc(alias = "sys::ffi::playdate_graphics::getDisplayFrame")] -#[inline(always)] -pub fn get_display_frame() -> Result<&'static mut [u8], ApiError> { Graphics::Default().get_display_frame() } - -/// After updating pixels in the buffer returned by [`get_frame`], -/// you must tell the graphics system which rows were updated. -/// -/// This function marks a contiguous range of rows as updated -/// (e.g., `markUpdatedRows(0, LCD_ROWS-1)` tells the system to update the entire display). -/// -/// Both `start` and `end` are __included__ in the range. -/// -/// This function is shorthand for [`Graphics::mark_updated_rows`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::markUpdatedRows`]. -#[doc(alias = "sys::ffi::playdate_graphics::markUpdatedRows")] -#[inline(always)] -pub fn mark_updated_rows(start: c_int, end: c_int) { Graphics::Default().mark_updated_rows(start, end) } - -/// Manually flushes the current frame buffer out to the display. -/// This function is automatically called after each pass through the run loop, -/// so there shouldn’t be any need to call it yourself. -/// -/// This function is shorthand for [`Graphics::display`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::display`]. -#[doc(alias = "sys::ffi::playdate_graphics::display")] -#[inline(always)] -pub fn display() { Graphics::Default().display() } - -/// Clears the entire display, filling it with `color`. -/// -/// This function is shorthand for [`Graphics::always`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::clear`]. -#[doc(alias = "sys::ffi::playdate_graphics::clear")] -#[inline(always)] -pub fn clear(color: color::Color) { clear_raw(color.into()) } - - -/// Clears the entire display, filling it with `color`. -/// -/// Same as [`clear`], but without conversion `Color` -> `LCDColor`. -/// That conversion is really cheap, -/// so this function is useful if you're working with `LCDColor` directly. -/// -/// This function is shorthand for [`Graphics::clear_raw`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::clear`]. -#[doc(alias = "sys::ffi::playdate_graphics::clear")] -#[inline(always)] -pub fn clear_raw(color: LCDColor) { Graphics::Default().clear_raw(color) } - -/// Sets the current clip rect in __screen__ coordinates. -/// -/// This function is shorthand for [`Graphics::set_screen_clip_rect`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::setScreenClipRect`]. -#[doc(alias = "sys::ffi::playdate_graphics::setScreenClipRect")] -#[inline(always)] -pub fn set_screen_clip_rect(x: c_int, y: c_int, width: c_int, height: c_int) { - Graphics::Default().set_screen_clip_rect(x, y, width, height) -} - -/// Offsets the origin point for all drawing calls to `x, y` (can be negative). -/// -/// This is useful, for example, for centering a "camera" -/// on a sprite that is moving around a world larger than the screen. -/// -/// This function is shorthand for [`Graphics::set_draw_offset`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::setDrawOffset`]. -#[doc(alias = "sys::ffi::playdate_graphics::setDrawOffset")] -#[inline(always)] -pub fn set_draw_offset(dx: c_int, dy: c_int) { Graphics::Default().set_draw_offset(dx, dy) } - -/// Sets the current clip rect, using __world__ coordinates that is, -/// the given rectangle will be translated by the current drawing offset. -/// -/// The clip rect is cleared at the beginning of each update. -/// -/// This function is shorthand for [`Graphics::set_clip_rect`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::setClipRect`]. -#[doc(alias = "sys::ffi::playdate_graphics::setClipRect")] -#[inline(always)] -pub fn set_clip_rect(x: c_int, y: c_int, width: c_int, height: c_int) { - Graphics::Default().set_clip_rect(x, y, width, height) -} - -/// Clears the current clip rect. -/// -/// This function is shorthand for [`Graphics::clear_clip_rect`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::clearClipRect`]. -#[doc(alias = "sys::ffi::playdate_graphics::clearClipRect")] -#[inline(always)] -pub fn clear_clip_rect() { Graphics::Default().clear_clip_rect() } - -/// Sets the background color shown when the display is offset -/// or for clearing dirty areas in the sprite system. -/// -/// This function is shorthand for [`Graphics::set_background_color`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::setBackgroundColor`]. -#[doc(alias = "sys::ffi::playdate_graphics::setBackgroundColor")] -#[inline(always)] -pub fn set_background_color(color: LCDSolidColor) { Graphics::Default().set_background_color(color) } - - -// -// Geometry -// - -/// Fills the polygon with vertices at the given coordinates -/// (an array of `2 * num_points` ints containing alternating x and y values) -/// using the given `color` and fill, or winding, `rule`. -/// -/// See [wikipedia](https://en.wikipedia.org/wiki/Nonzero-rule) for an explanation of the winding rule. -/// -/// This function is shorthand for [`Graphics::fill_polygon`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::fillPolygon`]. -#[doc(alias = "sys::ffi::playdate_graphics::fillPolygon")] -#[inline(always)] -pub fn fill_polygon(num_points: c_int, coords: &mut [c_int], color: LCDColor, rule: LCDPolygonFillRule) { - Graphics::Default().fill_polygon(num_points, coords, color, rule) -} - -/// Draws a line from `x1, y1` to `x2, y2` with a stroke width of `width`. -/// -/// This function is shorthand for [`Graphics::draw_line`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::drawLine`]. -#[doc(alias = "sys::ffi::playdate_graphics::drawLine")] -#[inline(always)] -pub fn draw_line(x1: c_int, y1: c_int, x2: c_int, y2: c_int, width: c_int, color: LCDColor) { - Graphics::Default().draw_line(x1, y1, x2, y2, width, color) -} - -/// Draws a filled triangle with points at `x1, y1`, `x2, y2`, and `x3, y3`. -/// -/// This function is shorthand for [`Graphics::fill_triangle`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::fillTriangle`]. -#[doc(alias = "sys::ffi::playdate_graphics::fillTriangle")] -#[inline(always)] -pub fn fill_triangle(x1: c_int, y1: c_int, x2: c_int, y2: c_int, x3: c_int, y3: c_int, color: LCDColor) { - Graphics::Default().fill_triangle(x1, y1, x2, y2, x3, y3, color); -} - -/// Draws a `width` by `height` rect at `x, y`. -/// -/// This function is shorthand for [`Graphics::draw_rect`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::drawRect`]. -#[doc(alias = "sys::ffi::playdate_graphics::drawRect")] -#[inline(always)] -pub fn draw_rect(x: c_int, y: c_int, width: c_int, height: c_int, color: LCDColor) { - Graphics::Default().draw_rect(x, y, width, height, color) -} - -/// Draws a filled `width` by `height` rect at `x, y`. -/// -/// This function is shorthand for [`Graphics::fill_rect`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::fillRect`]. -#[doc(alias = "sys::ffi::playdate_graphics::fillRect")] -#[inline(always)] -pub fn fill_rect(x: c_int, y: c_int, width: c_int, height: c_int, color: LCDColor) { - Graphics::Default().fill_rect(x, y, width, height, color) -} - -/// Draw an ellipse stroked inside the rect. -/// -/// Draws an ellipse inside the rectangle `x, y, width, height` of width `line_width` -/// (inset from the rectangle bounds). -/// -/// If `start_angle != end_angle`, this draws an arc between the given angles. -/// -/// Angles are given in degrees, clockwise from due north. -/// -/// This function is shorthand for [`Graphics::draw_ellipse`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::drawEllipse`]. -#[doc(alias = "sys::ffi::playdate_graphics::drawEllipse")] -#[inline(always)] -pub fn draw_ellipse(x: c_int, - y: c_int, - width: c_int, - height: c_int, - line_width: c_int, - start_angle: c_float, - end_angle: c_float, - color: LCDColor) { - Graphics::Default().draw_ellipse(x, y, width, height, line_width, start_angle, end_angle, color) -} - -/// Fills an ellipse inside the rectangle `x, y, width, height`. -/// -/// If `start_angle != end_angle`, this draws a wedge/Pacman between the given angles. -/// -/// Angles are given in degrees, clockwise from due north. -/// -/// This function is shorthand for [`Graphics::fill_ellipse`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::fillEllipse`]. -#[doc(alias = "sys::ffi::playdate_graphics::fillEllipse")] -#[inline(always)] -pub fn fill_ellipse(x: c_int, - y: c_int, - width: c_int, - height: c_int, - start_angle: c_float, - end_angle: c_float, - color: LCDColor) { - Graphics::Default().fill_ellipse(x, y, width, height, start_angle, end_angle, color) -} - - -/// Sets the end cap style used in the line drawing functions. -/// -/// This function is shorthand for [`Graphics::set_line_cap_style`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::setLineCapStyle`]. -#[doc(alias = "sys::ffi::playdate_graphics::setLineCapStyle")] -#[inline(always)] -pub fn set_line_cap_style(end_cap_style: LineCapStyle) { Graphics::Default().set_line_cap_style(end_cap_style) } - - #[derive(Debug, Clone, Copy)] pub struct Graphics(Api); @@ -350,6 +83,7 @@ impl Graphics { pub fn new_with(api: Api) -> Self { Self(api) } } +#[gen_api_shorthands::gen_shorthands] impl Graphics { /// Sets the pixel at `(x,y)` in the current drawing context (by default the screen) to the given `color`. /// Be aware that setting a pixel at a time is not very efficient: From f60262751d253ffe35476f7ec285807a50e696ff Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 21:00:31 +0400 Subject: [PATCH 09/17] use gen-api-shorthands in playdate-lua --- Cargo.lock | 1 + api/lua/Cargo.toml | 1 + api/lua/src/lib.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 195610f1..b333d794 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4280,6 +4280,7 @@ dependencies = [ name = "playdate-lua" version = "0.1.4" dependencies = [ + "playdate-gen-api-shorthands", "playdate-sys", "playdate-system", ] diff --git a/api/lua/Cargo.toml b/api/lua/Cargo.toml index 428f4f55..4b10c1c1 100644 --- a/api/lua/Cargo.toml +++ b/api/lua/Cargo.toml @@ -23,6 +23,7 @@ bindings-derive-debug = ["sys/bindings-derive-debug"] [dependencies] +gen-api-shorthands.workspace = true sys = { workspace = true, default-features = false } [dev-dependencies] diff --git a/api/lua/src/lib.rs b/api/lua/src/lib.rs index 3a33d7c2..7c5d666c 100644 --- a/api/lua/src/lib.rs +++ b/api/lua/src/lib.rs @@ -51,6 +51,7 @@ impl Lua { impl Lua {} +#[gen_api_shorthands::gen_shorthands] impl Lua { /// Adds the Lua function *f* to the Lua runtime, with name *name*. (*name* /// can be a table path using dots, e.g. if name = “mycode.myDrawingFunction” From 688322cc71cf0492bf091af01a38924dd7ffcd27 Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 21:08:33 +0400 Subject: [PATCH 10/17] use gen-api-shorthands in playdate-scoreboards --- api/scoreboards/Cargo.toml | 1 + api/scoreboards/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/api/scoreboards/Cargo.toml b/api/scoreboards/Cargo.toml index 07e542cf..b50b220b 100644 --- a/api/scoreboards/Cargo.toml +++ b/api/scoreboards/Cargo.toml @@ -23,6 +23,7 @@ bindings-derive-debug = ["sys/bindings-derive-debug"] [dependencies] +gen-api-shorthands.workspace = true sys = { workspace = true, default-features = false } erased_set = "0.8" diff --git a/api/scoreboards/src/lib.rs b/api/scoreboards/src/lib.rs index 82f51ca2..f3ad4a37 100644 --- a/api/scoreboards/src/lib.rs +++ b/api/scoreboards/src/lib.rs @@ -63,6 +63,7 @@ impl Scoreboards { } +#[gen_api_shorthands::gen_shorthands] impl Scoreboards { /// Requests to add score `value` to the board with given `board_id`. /// From f9b63f8735af9b75509a3255f53dd007178cf423 Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 21:08:41 +0400 Subject: [PATCH 11/17] use gen-api-shorthands in playdate-sound --- Cargo.lock | 2 ++ api/sound/Cargo.toml | 1 + api/sound/src/lib.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index b333d794..426a6e7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4299,6 +4299,7 @@ name = "playdate-scoreboards" version = "0.1.6" dependencies = [ "erased_set", + "playdate-gen-api-shorthands", "playdate-sys", "playdate-system", ] @@ -4320,6 +4321,7 @@ name = "playdate-sound" version = "0.4.4" dependencies = [ "playdate-fs", + "playdate-gen-api-shorthands", "playdate-graphics", "playdate-sys", "playdate-system", diff --git a/api/sound/Cargo.toml b/api/sound/Cargo.toml index a3f00661..8e4db6ae 100644 --- a/api/sound/Cargo.toml +++ b/api/sound/Cargo.toml @@ -24,6 +24,7 @@ bindings-derive-debug = ["sys/bindings-derive-debug", "fs/bindings-derive-debug" [dependencies] +gen-api-shorthands.workspace = true sys = { workspace = true, default-features = false } fs = { workspace = true, default-features = false } diff --git a/api/sound/src/lib.rs b/api/sound/src/lib.rs index 2bad57c6..9206e530 100644 --- a/api/sound/src/lib.rs +++ b/api/sound/src/lib.rs @@ -58,6 +58,7 @@ impl Sound { pub fn new_with(api: Api) -> Self { Self(api) } } +#[gen_api_shorthands::gen_shorthands] impl Sound { /// Returns the sound engine’s current time value, in units of sample frames, `44100` per second. /// From 07b02c0b350775c797b4cea202eb5c336ee4fa8f Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 21:18:51 +0400 Subject: [PATCH 12/17] bump touched crates version --- Cargo.lock | 16 ++++++++-------- api/ctrl/Cargo.toml | 2 +- api/display/Cargo.toml | 2 +- api/gfx/Cargo.toml | 2 +- api/lua/Cargo.toml | 2 +- api/scoreboards/Cargo.toml | 2 +- api/sound/Cargo.toml | 2 +- api/sprite/Cargo.toml | 2 +- api/system/Cargo.toml | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 426a6e7a..6be26c98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4199,7 +4199,7 @@ dependencies = [ [[package]] name = "playdate-controls" -version = "0.3.8" +version = "0.3.9" dependencies = [ "playdate-display", "playdate-gen-api-shorthands", @@ -4240,7 +4240,7 @@ dependencies = [ [[package]] name = "playdate-display" -version = "0.3.8" +version = "0.3.9" dependencies = [ "playdate-gen-api-shorthands", "playdate-sys", @@ -4266,7 +4266,7 @@ dependencies = [ [[package]] name = "playdate-graphics" -version = "0.4.3" +version = "0.4.4" dependencies = [ "playdate-color", "playdate-display", @@ -4278,7 +4278,7 @@ dependencies = [ [[package]] name = "playdate-lua" -version = "0.1.4" +version = "0.1.5" dependencies = [ "playdate-gen-api-shorthands", "playdate-sys", @@ -4296,7 +4296,7 @@ dependencies = [ [[package]] name = "playdate-scoreboards" -version = "0.1.6" +version = "0.1.7" dependencies = [ "erased_set", "playdate-gen-api-shorthands", @@ -4318,7 +4318,7 @@ dependencies = [ [[package]] name = "playdate-sound" -version = "0.4.4" +version = "0.4.5" dependencies = [ "playdate-fs", "playdate-gen-api-shorthands", @@ -4329,7 +4329,7 @@ dependencies = [ [[package]] name = "playdate-sprite" -version = "0.3.2" +version = "0.3.3" dependencies = [ "playdate-display", "playdate-graphics", @@ -4368,7 +4368,7 @@ dependencies = [ [[package]] name = "playdate-system" -version = "0.3.15" +version = "0.3.16" dependencies = [ "playdate-gen-api-shorthands", "playdate-sys", diff --git a/api/ctrl/Cargo.toml b/api/ctrl/Cargo.toml index 357bce92..5d75fd38 100644 --- a/api/ctrl/Cargo.toml +++ b/api/ctrl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-controls" -version = "0.3.8" +version = "0.3.9" readme = "README.md" description = "High-level controls API built on-top of Playdate API" keywords = ["playdate", "sdk", "api", "gamedev"] diff --git a/api/display/Cargo.toml b/api/display/Cargo.toml index c4a5889a..a6587bb0 100644 --- a/api/display/Cargo.toml +++ b/api/display/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-display" -version = "0.3.8" +version = "0.3.9" readme = "README.md" description = "High-level Display API built on-top of Playdate API" keywords = ["playdate", "sdk", "api", "gamedev"] diff --git a/api/gfx/Cargo.toml b/api/gfx/Cargo.toml index da2a599e..040983a7 100644 --- a/api/gfx/Cargo.toml +++ b/api/gfx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-graphics" -version = "0.4.3" +version = "0.4.4" readme = "README.md" description = "High-level graphics API built on-top of Playdate API" keywords = ["playdate", "sdk", "api", "gamedev"] diff --git a/api/lua/Cargo.toml b/api/lua/Cargo.toml index 4b10c1c1..7835d6b0 100644 --- a/api/lua/Cargo.toml +++ b/api/lua/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-lua" -version = "0.1.4" +version = "0.1.5" readme = "README.md" description = "High-level Lua API built on-top of Playdate API" keywords = ["playdate", "sdk", "api", "gamedev"] diff --git a/api/scoreboards/Cargo.toml b/api/scoreboards/Cargo.toml index b50b220b..3af7e10c 100644 --- a/api/scoreboards/Cargo.toml +++ b/api/scoreboards/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-scoreboards" -version = "0.1.6" +version = "0.1.7" readme = "README.md" description = "High-level Scoreboards API built on-top of Playdate API" keywords = ["playdate", "sdk", "api", "gamedev"] diff --git a/api/sound/Cargo.toml b/api/sound/Cargo.toml index 8e4db6ae..aa332dcb 100644 --- a/api/sound/Cargo.toml +++ b/api/sound/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-sound" -version = "0.4.4" +version = "0.4.5" readme = "README.md" description = "High-level sound API built on-top of Playdate API" keywords = ["playdate", "sdk", "api", "gamedev"] diff --git a/api/sprite/Cargo.toml b/api/sprite/Cargo.toml index 490c027b..0ccecad3 100644 --- a/api/sprite/Cargo.toml +++ b/api/sprite/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-sprite" -version = "0.3.2" +version = "0.3.3" readme = "README.md" description = "High-level sprite API built on-top of Playdate API" keywords = ["playdate", "sdk", "api", "gamedev"] diff --git a/api/system/Cargo.toml b/api/system/Cargo.toml index 806bd766..d7086738 100644 --- a/api/system/Cargo.toml +++ b/api/system/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-system" -version = "0.3.15" +version = "0.3.16" readme = "README.md" description = "High-level System API built on-top of Playdate API" keywords = ["playdate", "sdk", "api", "gamedev"] From bd97cb055a6151fcb1fc301b2772d6171e8fe746 Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 21:21:43 +0400 Subject: [PATCH 13/17] revert sprite version --- Cargo.lock | 2 +- api/sprite/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6be26c98..dbe61eeb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4329,7 +4329,7 @@ dependencies = [ [[package]] name = "playdate-sprite" -version = "0.3.3" +version = "0.3.2" dependencies = [ "playdate-display", "playdate-graphics", diff --git a/api/sprite/Cargo.toml b/api/sprite/Cargo.toml index 0ccecad3..490c027b 100644 --- a/api/sprite/Cargo.toml +++ b/api/sprite/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-sprite" -version = "0.3.3" +version = "0.3.2" readme = "README.md" description = "High-level sprite API built on-top of Playdate API" keywords = ["playdate", "sdk", "api", "gamedev"] From f2b5e38e0456ed4e9009735f4d23affff41d3010 Mon Sep 17 00:00:00 2001 From: kana Date: Sun, 16 Feb 2025 21:36:49 +0400 Subject: [PATCH 14/17] bump bindgen version --- Cargo.lock | 2 +- support/bindgen/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dbe61eeb..d76ab883 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4139,7 +4139,7 @@ dependencies = [ [[package]] name = "playdate-bindgen" -version = "0.2.2" +version = "0.2.3" dependencies = [ "bindgen", "clap", diff --git a/support/bindgen/Cargo.toml b/support/bindgen/Cargo.toml index 6fa7c653..c6e79101 100644 --- a/support/bindgen/Cargo.toml +++ b/support/bindgen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-bindgen" -version = "0.2.2" +version = "0.2.3" readme = "README.md" description = "Preconfigured Bindgen with extra codegen for Playdate C-API." keywords = ["playdate", "bindings", "ffi", "code-generation"] From cd45292ddb4c02a575aaad73230cdeb0fbb19836 Mon Sep 17 00:00:00 2001 From: kana Date: Mon, 17 Feb 2025 08:47:04 +0400 Subject: [PATCH 15/17] Mutate original method instead of creating new fn --- support/gen-api-shorthands/src/lib.rs | 120 +++++++++++++++----------- 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/support/gen-api-shorthands/src/lib.rs b/support/gen-api-shorthands/src/lib.rs index bd3433ea..4a7198e0 100644 --- a/support/gen-api-shorthands/src/lib.rs +++ b/support/gen-api-shorthands/src/lib.rs @@ -6,7 +6,7 @@ use std::assert_matches::assert_matches; use derive_syn_parse::Parse; use proc_macro::TokenStream; use quote::quote; -use syn::{parse_macro_input, FnArg, Ident, ImplItem, ImplItemFn, ItemImpl, Signature, Token, Visibility}; +use syn::{parse_macro_input, spanned::Spanned, FnArg, Ident, ImplItem, ImplItemFn, ItemImpl, Token, Visibility}; #[derive(Parse)] struct AttrValue { @@ -18,75 +18,91 @@ struct AttrValue { #[proc_macro_attribute] pub fn gen_shorthands(attr: TokenStream, item: TokenStream) -> TokenStream { let source_impl: proc_macro2::TokenStream = item.clone().into(); - let ItemImpl { trait_, items, self_ty, .. } = parse_macro_input!(item as ItemImpl); + let (api, impl_items) = parse_api_impl(parse_macro_input!(item as ItemImpl)); - let self_ty = match *self_ty { + let shorthands = impl_items.into_iter() + .map(parse_method) + .map(|method| into_shorthand(&api, method)) + .collect::>(); + + let shorthands = if attr.is_empty() { + quote! { #(#shorthands)* } + } else { + let AttrValue { mod_vis, mod_token, mod_name } = parse_macro_input!(attr as AttrValue); + quote! { + #mod_vis #mod_token #mod_name { + use super::*; + #(#shorthands)* + } + } + }; + + TokenStream::from(quote! { + #source_impl + #shorthands + }) +} + +fn parse_api_impl(impl_: ItemImpl) -> (Ident, Vec) { + let api = match *impl_.self_ty { syn::Type::Path(syn::TypePath { qself: None, path }) => path .segments.last().expect("empty path") .ident.clone(), _ => panic!("only simple paths are supported"), }; - assert!(trait_.is_none(), "trait impls are not supported"); + assert!(impl_.trait_.is_none(), "trait impls are not supported"); - let shorthands = items.into_iter().map(|item| { - let ImplItem::Fn(ImplItemFn { attrs, defaultness, sig, vis: _, block: _ }) = item else { - panic!("only methods are supported"); - }; + return (api, impl_.items); +} - let Signature { constness, asyncness, unsafety, abi, fn_token: _, ident, generics, paren_token: _, inputs, variadic, output } = sig; - let where_clause = &generics.where_clause; +fn parse_method(item: ImplItem) -> ImplItemFn { + let ImplItem::Fn(method) = item else { panic!("only methods are supported"); }; - assert!(defaultness.is_none(), "default methods are not supported"); - assert!(constness.is_none(), "const methods are not supported"); - assert!(asyncness.is_none(), "async methods are not supported"); - assert!(unsafety.is_none(), "unsafe methods are not supported"); - assert!(abi.is_none(), "extern methods are not supported"); - assert!(variadic.is_none(), "variadic methods are not supported"); + assert!(method.defaultness.is_none(), "default methods are not supported"); + assert!(method.sig.constness.is_none(), "const methods are not supported"); + assert!(method.sig.asyncness.is_none(), "async methods are not supported"); + assert!(method.sig.unsafety.is_none(), "unsafe methods are not supported"); + assert!(method.sig.abi.is_none(), "extern methods are not supported"); + assert!(method.sig.variadic.is_none(), "variadic methods are not supported"); + assert_matches!(method.sig.inputs.first(), Some(FnArg::Receiver(_)), "only methods are supported"); - assert_matches!(inputs.first(), Some(FnArg::Receiver(_)), "only methods are supported"); + return method; +} - let inputs = inputs.iter() - .filter_map(|input| match input { - FnArg::Receiver(_) => None, - FnArg::Typed(arg) => Some(arg), - }) - .collect::>(); +fn into_shorthand(api: &Ident, mut method: ImplItemFn) -> ImplItemFn { + let method_name = method.sig.ident.clone(); - let inputs_args = inputs.iter() - .map(|pat| &pat.pat) - .collect::>(); + // Remove the receiver from the method signature + method.sig.inputs = method.sig.inputs.into_iter().filter(|input| matches!(input, FnArg::Typed(_))).collect(); - let shorthand_doc = quote! { concat!(" This function is shorthand for [`", stringify!(#self_ty), "::", stringify!(#ident), "`], using default ZST end-point.") }; - let shorthand_doc: proc_macro2::TokenStream = TokenStream::from(shorthand_doc).expand_expr().unwrap().into(); - quote! { - #(#attrs)* - #[doc = ""] - #[doc = #shorthand_doc] - #[inline(always)] - pub fn #ident #generics ( #(#inputs),* ) #output #where_clause { - #self_ty::Default().#ident( #(#inputs_args),* ) - } - } - }).collect::>(); + // All shorthand functions are public + method.vis = Visibility::Public(Token![pub](method.span())); - let mut shorthands = quote! { #(#shorthands)* }; - if !attr.is_empty() { - let AttrValue { mod_vis, mod_token, mod_name } = parse_macro_input!(attr as AttrValue); + // All shorthand functions should inline + method.attrs.append({ + let shorthand_doc_msg = quote! { concat!(" This function is shorthand for [`", stringify!(#api), "::", stringify!(#method_name), "`], using default ZST end-point.") }; + let shorthand_doc_msg: proc_macro2::TokenStream = TokenStream::from(shorthand_doc_msg).expand_expr().unwrap().into(); - shorthands = quote! { - #mod_vis #mod_token #mod_name { - use super::*; + &mut vec![ + syn::parse_quote! { #[doc = ""] }, + syn::parse_quote! { #[doc = #shorthand_doc_msg] }, + syn::parse_quote! { #[inline(always)] }, + ] + }); - #shorthands - } - }; - } - TokenStream::from(quote! { - #source_impl - #shorthands - }) + // Just call the method from the default end-point + method.block = { + let args = method.sig.inputs.iter().filter_map(|input| match input { + FnArg::Receiver(_) => None, + FnArg::Typed(pat) => Some(&pat.pat), + }).collect::>(); + + syn::parse_quote! { { #api::Default().#method_name( #(#args),* ) } } + }; + + return method; } From 908db5fe9ce8ccd6ff0e8f0ba8caabb74d357fe4 Mon Sep 17 00:00:00 2001 From: kana Date: Mon, 17 Feb 2025 20:17:28 +0400 Subject: [PATCH 16/17] Get rid of proc_macro_expand, assert_matches and derive_syn_parse --- Cargo.lock | 12 ---- support/gen-api-shorthands/Cargo.toml | 2 - support/gen-api-shorthands/src/lib.rs | 86 ++++++++++++++++----------- 3 files changed, 51 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d76ab883..33a2f329 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1243,17 +1243,6 @@ dependencies = [ "serde", ] -[[package]] -name = "derive-syn-parse" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - [[package]] name = "derive_arbitrary" version = "1.4.1" @@ -4258,7 +4247,6 @@ dependencies = [ name = "playdate-gen-api-shorthands" version = "0.1.0" dependencies = [ - "derive-syn-parse", "proc-macro2", "quote", "syn 2.0.98", diff --git a/support/gen-api-shorthands/Cargo.toml b/support/gen-api-shorthands/Cargo.toml index 299a916d..539268b0 100644 --- a/support/gen-api-shorthands/Cargo.toml +++ b/support/gen-api-shorthands/Cargo.toml @@ -2,7 +2,6 @@ name = "playdate-gen-api-shorthands" version = "0.1.0" keywords = ["playdate", "bindings", "code-generation"] -categories = ["development-tools::ffi", "development-tools::build-utils"] edition.workspace = true license.workspace = true authors = ["kana "] @@ -13,7 +12,6 @@ repository.workspace = true proc-macro = true [dependencies] -derive-syn-parse = "0.2.0" proc-macro2.workspace = true quote.workspace = true syn.workspace = true diff --git a/support/gen-api-shorthands/src/lib.rs b/support/gen-api-shorthands/src/lib.rs index 4a7198e0..cad07ac9 100644 --- a/support/gen-api-shorthands/src/lib.rs +++ b/support/gen-api-shorthands/src/lib.rs @@ -1,48 +1,65 @@ -#![feature(assert_matches)] -#![feature(proc_macro_expand)] - -use std::assert_matches::assert_matches; - -use derive_syn_parse::Parse; -use proc_macro::TokenStream; use quote::quote; -use syn::{parse_macro_input, spanned::Spanned, FnArg, Ident, ImplItem, ImplItemFn, ItemImpl, Token, Visibility}; - -#[derive(Parse)] -struct AttrValue { - mod_vis: Visibility, - mod_token: Token![mod], - mod_name: Ident, -} +use syn::{parse::Parse, parse_macro_input, spanned::Spanned, FnArg, Ident, ImplItem, ImplItemFn, ItemImpl, Token, Visibility}; #[proc_macro_attribute] -pub fn gen_shorthands(attr: TokenStream, item: TokenStream) -> TokenStream { +pub fn gen_shorthands(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream { let source_impl: proc_macro2::TokenStream = item.clone().into(); + + let target_options = parse_macro_input!(attr as GenTargetOptions); let (api, impl_items) = parse_api_impl(parse_macro_input!(item as ItemImpl)); let shorthands = impl_items.into_iter() - .map(parse_method) - .map(|method| into_shorthand(&api, method)) + .map(parse_api_method) + .map(|method| api_method_into_shorthand(&api, method)) .collect::>(); - let shorthands = if attr.is_empty() { - quote! { #(#shorthands)* } - } else { - let AttrValue { mod_vis, mod_token, mod_name } = parse_macro_input!(attr as AttrValue); - quote! { - #mod_vis #mod_token #mod_name { - use super::*; - #(#shorthands)* - } - } - }; + let shorthands = target_options.apply(quote! { #(#shorthands)* }); - TokenStream::from(quote! { + proc_macro::TokenStream::from(quote! { #source_impl #shorthands }) } +enum GenTargetOptions { + InPlace, + GenMod { + mod_vis: Visibility, + mod_token: Token![mod], + mod_name: Ident, + } +} + +impl Parse for GenTargetOptions { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + if input.is_empty() { + return Ok(GenTargetOptions::InPlace); + } + + Ok(GenTargetOptions::GenMod { + mod_vis: input.parse()?, + mod_token: input.parse()?, + mod_name: input.parse()?, + }) + } +} + +impl GenTargetOptions { + fn apply(self, item: proc_macro2::TokenStream) -> proc_macro2::TokenStream { + match self { + GenTargetOptions::InPlace => item, + GenTargetOptions::GenMod { mod_vis, mod_token, mod_name } => { + quote! { + #mod_vis #mod_token #mod_name { + use super::*; + #item + } + } + } + } + } +} + fn parse_api_impl(impl_: ItemImpl) -> (Ident, Vec) { let api = match *impl_.self_ty { syn::Type::Path(syn::TypePath { qself: None, path }) => path @@ -56,7 +73,7 @@ fn parse_api_impl(impl_: ItemImpl) -> (Ident, Vec) { return (api, impl_.items); } -fn parse_method(item: ImplItem) -> ImplItemFn { +fn parse_api_method(item: ImplItem) -> ImplItemFn { let ImplItem::Fn(method) = item else { panic!("only methods are supported"); }; assert!(method.defaultness.is_none(), "default methods are not supported"); @@ -65,12 +82,12 @@ fn parse_method(item: ImplItem) -> ImplItemFn { assert!(method.sig.unsafety.is_none(), "unsafe methods are not supported"); assert!(method.sig.abi.is_none(), "extern methods are not supported"); assert!(method.sig.variadic.is_none(), "variadic methods are not supported"); - assert_matches!(method.sig.inputs.first(), Some(FnArg::Receiver(_)), "only methods are supported"); + assert!(matches!(method.sig.inputs.first(), Some(FnArg::Receiver(_))), "only methods are supported"); return method; } -fn into_shorthand(api: &Ident, mut method: ImplItemFn) -> ImplItemFn { +fn api_method_into_shorthand(api: &Ident, mut method: ImplItemFn) -> ImplItemFn { let method_name = method.sig.ident.clone(); // Remove the receiver from the method signature @@ -83,8 +100,7 @@ fn into_shorthand(api: &Ident, mut method: ImplItemFn) -> ImplItemFn { // All shorthand functions should inline method.attrs.append({ - let shorthand_doc_msg = quote! { concat!(" This function is shorthand for [`", stringify!(#api), "::", stringify!(#method_name), "`], using default ZST end-point.") }; - let shorthand_doc_msg: proc_macro2::TokenStream = TokenStream::from(shorthand_doc_msg).expand_expr().unwrap().into(); + let shorthand_doc_msg = format!("This function is shorthand for [`{}::{}`], using default ZST end-point.", api, method_name); &mut vec![ syn::parse_quote! { #[doc = ""] }, From 0312d9d294ca4ac19dd442d4f438503090d1f140 Mon Sep 17 00:00:00 2001 From: kana Date: Tue, 18 Feb 2025 17:17:40 +0400 Subject: [PATCH 17/17] use gen-api-shorthands in playdate-graphics::{text, bitmap} --- api/gfx/src/bitmap/bitmap.rs | 128 +-------------------- api/gfx/src/text.rs | 215 +---------------------------------- 2 files changed, 3 insertions(+), 340 deletions(-) diff --git a/api/gfx/src/bitmap/bitmap.rs b/api/gfx/src/bitmap/bitmap.rs index 50af917b..59c95616 100644 --- a/api/gfx/src/bitmap/bitmap.rs +++ b/api/gfx/src/bitmap/bitmap.rs @@ -595,133 +595,9 @@ impl core::fmt::Debug for BitmapData<'_> { } } +pub use frame_buffer_bitmap as copy_frame_buffer_bitmap; -// -// Global Bitmap-related methods -// - -/// Only valid in the Simulator, -/// returns the debug framebuffer as a bitmap. -/// -/// Returns error on device. -/// -/// This function is shorthand for [`Graphics::debug_bitmap`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getDebugBitmap`]. -#[doc(alias = "sys::ffi::playdate_graphics::getDebugBitmap")] -#[inline(always)] -pub fn debug_bitmap() -> Result, ApiError> { Graphics::Default().debug_bitmap() } - -/// Returns a bitmap containing the contents of the display buffer. -/// -/// __The system owns this bitmap—​do not free it.__ -/// -/// This function is shorthand for [`Graphics::display_buffer_bitmap`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getDisplayBufferBitmap`]. -#[doc(alias = "sys::ffi::playdate_graphics::getDisplayBufferBitmap")] -#[inline(always)] -pub fn display_buffer_bitmap() -> Result, Error> { - Graphics::Default().display_buffer_bitmap() -} - -/// Returns a copy the contents of the working frame buffer as a bitmap. -/// -/// The caller is responsible for freeing the returned bitmap, it will automatically on drop. -/// -/// This function is shorthand for [`Graphics::frame_buffer_bitmap`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::copyFrameBufferBitmap`]. -#[doc(alias = "sys::ffi::playdate_graphics::copyFrameBufferBitmap")] -#[inline(always)] -pub fn copy_frame_buffer_bitmap() -> Result, Error> { - Graphics::Default().frame_buffer_bitmap() -} - - -/// Sets the stencil used for drawing. -/// -/// If the `tile` is `true` the stencil image will be tiled. -/// -/// Tiled stencils must have width equal to a multiple of 32 pixels. -/// -/// This function is shorthand for [`Graphics::set_stencil_tiled`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::setStencilImage`]. -#[doc(alias = "sys::ffi::playdate_graphics::setStencilImage")] -#[inline(always)] -pub fn set_stencil_tiled(image: &impl AnyBitmap, tile: bool) { - Graphics::Default().set_stencil_tiled(image, tile) -} - -/// Sets the stencil used for drawing. -/// For a tiled stencil, use [`set_stencil_tiled`] instead. -/// -/// NOTE: Officially deprecated in favor of [`set_stencil_tiled`], which adds a `tile` flag -/// -/// This function is shorthand for [`Graphics::set_stencil`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::setStencil`]. -#[doc(alias = "sys::ffi::playdate_graphics::setStencil")] -#[inline(always)] -pub fn set_stencil(image: &impl AnyBitmap) { Graphics::Default().set_stencil(image) } - -/// Sets the mode used for drawing bitmaps. -/// -/// Note that text drawing uses bitmaps, so this affects how fonts are displayed as well. -/// -/// This function is shorthand for [`Graphics::set_draw_mode`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::setDrawMode`]. -#[doc(alias = "sys::ffi::playdate_graphics::setDrawMode")] -#[inline(always)] -pub fn set_draw_mode(mode: BitmapDrawMode) -> BitmapDrawMode { Graphics::Default().set_draw_mode(mode) } - -/// Push a new drawing context for drawing into the given bitmap. -/// -/// If underlying ptr in the `target` is `null`, the drawing functions will use the display framebuffer. -/// This mostly should not happen, just for note. -/// -/// To clear entire context use [`clear_context`]. -/// -/// This function is shorthand for [`Graphics::push_context`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::pushContext`]. -#[doc(alias = "sys::ffi::playdate_graphics::pushContext")] -#[inline(always)] -pub fn push_context(target: &impl AnyBitmap) { Graphics::Default().push_context(target) } - -/// Resets drawing context for drawing into the system display framebuffer. -/// -/// So drawing functions will use the display framebuffer. -/// -/// This function is shorthand for [`Graphics::clear_context`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::pushContext`]. -#[doc(alias = "sys::ffi::playdate_graphics::pushContext")] -#[inline(always)] -pub fn clear_context() { Graphics::Default().clear_context() } - -/// Pops a context off the stack (if any are left), -/// restoring the drawing settings from before the context was pushed. -/// -/// This function is shorthand for [`Graphics::pop_context`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::popContext`]. -#[doc(alias = "sys::ffi::playdate_graphics::popContext")] -#[inline(always)] -pub fn pop_context() { Graphics::Default().pop_context() } - - +#[gen_api_shorthands::gen_shorthands] impl Graphics { /// Only valid in the Simulator, /// returns the debug framebuffer as a bitmap. diff --git a/api/gfx/src/text.rs b/api/gfx/src/text.rs index 84279993..65e70bfa 100644 --- a/api/gfx/src/text.rs +++ b/api/gfx/src/text.rs @@ -14,220 +14,7 @@ use crate::Graphics; use crate::bitmap::BitmapRef; use crate::error::{Error, ApiError}; - -/// Draws the given `text` using the provided coords `x`, `y`. -/// -/// Encoding is always `StringEncoding::UTF8`. -/// If another encoding is desired, use [`draw_text_cstr`] instead. -/// -/// If no `font` has been set with [`set_font`], -/// the default system font `Asheville Sans 14 Light` is used. -/// -/// This function is shorthand for [`Graphics::draw_text`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::drawText`]. -#[doc(alias = "sys::ffi::playdate_graphics::drawText")] -#[inline(always)] -pub fn draw_text>(text: S, x: c_int, y: c_int) -> Result { - Graphics::Default().draw_text(text, x, y) -} - -/// Draws the given `text` using the provided options. -/// -/// If no `font` has been set with [`set_font`], -/// the default system font `Asheville Sans 14 Light` is used. -/// -/// Same as [`draw_text`] but takes a [`sys::ffi::CStr`], -/// but little bit more efficient. -/// -/// This function is shorthand for [`Graphics::draw_text_cstr`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::drawText`]. -#[doc(alias = "sys::ffi::playdate_graphics::drawText")] -#[inline(always)] -pub fn draw_text_cstr(text: &CStr, encoding: StringEncoding, x: c_int, y: c_int) -> c_int { - Graphics::Default().draw_text_cstr(text, encoding, x, y) -} - - -/// Returns the width of the given `text` in the given `font`. -/// -/// This function is shorthand for [`Graphics::get_text_width`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getTextWidth`]. -#[doc(alias = "sys::ffi::playdate_graphics::getTextWidth")] -#[inline(always)] -pub fn get_text_width>(text: S, font: Option<&Font>, tracking: c_int) -> Result { - Graphics::Default().get_text_width(text, font, tracking) -} - -/// Returns the width of the given `text` in the given `font`. -/// -/// Same as [`get_text_width`] but takes a [`sys::ffi::CStr`], -/// but little bit more efficient. -/// -/// This function is shorthand for [`Graphics::get_text_width_cstr`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getTextWidth`]. -#[doc(alias = "sys::ffi::playdate_graphics::getTextWidth")] -#[inline(always)] -pub fn get_text_width_cstr(text: &CStr, encoding: StringEncoding, font: Option<&Font>, tracking: c_int) -> c_int { - Graphics::Default().get_text_width_cstr(text, encoding, font, tracking) -} - - -/// Returns the height of the given `font`. -/// -/// This function is shorthand for [`Graphics::get_font_height`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getFontHeight`]. -#[doc(alias = "sys::ffi::playdate_graphics::getFontHeight")] -#[inline(always)] -pub fn get_font_height(font: &Font) -> u8 { Graphics::Default().get_font_height(font) } - -/// Sets the `font` to use in subsequent [`draw_text`] calls. -/// -/// This function is shorthand for [`Graphics::set_font`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::setFont`]. -#[doc(alias = "sys::ffi::playdate_graphics::setFont")] -#[inline(always)] -pub fn set_font(font: &Font) { Graphics::Default().set_font(font) } - -/// Returns the kerning adjustment between characters `glyph_code` and `next_code` as specified by the font -/// -/// This function is shorthand for [`Graphics::get_glyph_kerning`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getGlyphKerning`]. -#[doc(alias = "sys::ffi::playdate_graphics::getGlyphKerning")] -#[inline(always)] -pub fn get_glyph_kerning(glyph: &Glyph, glyph_code: u32, next_code: u32) -> c_int { - Graphics::Default().get_glyph_kerning(glyph, glyph_code, next_code) -} - -/// Returns an [`Glyph`] object for character `c` in [`FontPage`] page, -/// -/// To also get the glyph’s bitmap and `advance` value -/// use [`get_page_glyph_with_bitmap`] instead. -/// -/// This function is shorthand for [`Graphics::get_page_glyph`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getPageGlyph`]. -#[doc(alias = "sys::ffi::playdate_graphics::getPageGlyph")] -#[inline(always)] -pub fn get_page_glyph(page: &FontPage, c: u32) -> Result { - Graphics::Default().get_page_glyph(page, c) -} - -/// Returns an [`Glyph`] object for character `c` in [`FontPage`] page, -/// and optionally returns the glyph’s bitmap and `advance` value. -/// -/// If bitmap is not needed, use [`get_page_glyph`] instead. -/// -/// This function is shorthand for [`Graphics::get_page_glyph_with_bitmap`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getPageGlyph`]. -#[doc(alias = "sys::ffi::playdate_graphics::getPageGlyph")] -#[inline(always)] -pub fn get_page_glyph_with_bitmap<'p>(page: &'p FontPage, - c: u32, - advance: &mut c_int) - -> Result<(Glyph, BitmapRef<'p>), Error> { - Graphics::Default().get_page_glyph_with_bitmap(page, c, advance) -} - - -/// Returns an [`FontPage`] object for the given character code `c`. -/// -/// Each [`FontPage`] contains information for 256 characters; -/// specifically, if `(c1 & ~0xff) == (c2 & ~0xff)`, -/// then `c1` and `c2` belong to the same page and the same [`FontPage`] -/// can be used to fetch the character data for both instead of searching for the page twice. -/// -/// This function is shorthand for [`Graphics::get_font_page`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getFontPage`]. -#[doc(alias = "sys::ffi::playdate_graphics::getFontPage")] -#[inline(always)] -pub fn get_font_page(font: &Font, c: u32) -> Result { - Graphics::Default().get_font_page(font, c) -} - - -/// Returns the [`Font`] object for the font file at `path`. -/// -/// This function is shorthand for [`Graphics::load_font`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::loadFont`]. -#[doc(alias = "sys::ffi::playdate_graphics::loadFont")] -#[inline(always)] -pub fn load_font>(path: P) -> Result { Graphics::Default().load_font(path) } - - -/// ⚠️ Caution: This function is not tested. -/// -/// Returns an [`Font`] object wrapping the LCDFontData data -/// comprising the contents (minus 16-byte header) of an uncompressed pft file. -/// -/// The `wide` corresponds to the flag in the header indicating -/// whether the font contains glyphs at codepoints above `U+1FFFF`. -/// -/// This function is shorthand for [`Graphics::make_font_from_bytes`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::makeFontFromData`]. -#[doc(alias = "sys::ffi::playdate_graphics::makeFontFromData")] -#[inline(always)] -pub fn make_font_from_bytes(data: &[u8], wide: c_int) -> Result { - Graphics::Default().make_font_from_bytes(data, wide) -} - - -/// Sets the leading adjustment (added to the leading specified in the font) to use when drawing text. -/// -/// This function is shorthand for [`Graphics::set_text_leading`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::setTextLeading`]. -#[doc(alias = "sys::ffi::playdate_graphics::setTextLeading")] -#[inline(always)] -pub fn set_text_leading(line_height_adjustment: c_int) { - Graphics::Default().set_text_leading(line_height_adjustment) -} - -/// Sets the tracking to use when drawing text. -/// -/// This function is shorthand for [`Graphics::set_text_tracking`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::setTextTracking`]. -#[doc(alias = "sys::ffi::playdate_graphics::setTextTracking")] -#[inline(always)] -pub fn set_text_tracking(tracking: c_int) { Graphics::Default().set_text_tracking(tracking) } - - -/// Gets the tracking used when drawing text. -/// -/// This function is shorthand for [`Graphics::set_text_tracking`], -/// using default ZST end-point. -/// -/// Equivalent to [`sys::ffi::playdate_graphics::getTextTracking`]. -#[doc(alias = "sys::ffi::playdate_graphics::getTextTracking")] -#[inline(always)] -pub fn get_text_tracking() -> c_int { Graphics::Default().get_text_tracking() } - - +#[gen_api_shorthands::gen_shorthands] impl Graphics { /// Draws the given `text` using the provided coords `x`, `y`. ///