Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge fns DrawCx::text_effects, text; remove min_spec; tweaks #458

Merged
merged 8 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

- Merge fns `DrawCx::text_effects` and `text` (#458)
- Remove feature `min_spec` (#458)

## [0.15.0] — 2024-12-02

Most significant is the addition of the `Collection` trait representing a list or tuple of widgets.
Expand Down
6 changes: 2 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,15 @@ default = ["minimal", "view", "image", "resvg", "clipboard", "markdown", "shapin
# All standard test target features
stable = ["default", "x11", "serde", "toml", "yaml", "json", "ron", "macros_log"]
# Enables all "recommended" features for nightly rustc
nightly = ["stable", "min_spec"]
nightly = ["stable"]
# Additional, less recommendation-worthy features
experimental = ["dark-light", "recursive-layout-widgets", "unsafe_node"]

# Enable dynamic linking (faster linking via an extra run-time dependency):
dynamic = ["dep:kas-dylib"]

# Use min_specialization (enables access key underlining for AccessLabel)
min_spec = ["kas-widgets/min_spec"]
# Use full specialization
spec = ["min_spec", "kas-core/spec"]
spec = ["kas-core/spec"]

######### optional dependencies / features #########

Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ See [Cargo.toml](https://github.com/kas-gui/kas/blob/master/Cargo.toml#L22).
[kas]: https://docs.rs/kas


Size
----

To reduce binary size, add this to your `Cargo.toml`:
```toml
[profile.release]
strip = true
opt-level = "z"
```

You might also consider using feature `dynamic` if wishing to ship multiple
binaries with shared libraries (Rust's `libstd` and `libkas_dylib`); note
however that these are not ABI-stable.


Copyright and Licence
---------------------

Expand Down
8 changes: 7 additions & 1 deletion crates/kas-core/src/draw/draw_shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,10 @@ pub trait DrawSharedImpl: Any {
/// Draw text with a colour and effects
///
/// The effects list does not contain colour information, but may contain
/// underlining/strikethrough information. It may be empty.
/// underlining/strikethrough information.
///
/// If `effects` is empty or all [`Effect::flags`] are default then it is
/// equivalent (and faster) to call [`Self::draw_text`] instead.
fn draw_text_effects(
&mut self,
draw: &mut Self::Draw,
Expand All @@ -202,6 +205,9 @@ pub trait DrawSharedImpl: Any {
/// The `effects` list provides both underlining and colour information.
/// If the `effects` list is empty or the first entry has `start > 0`, a
/// default entity will be assumed.
///
/// If `effects` is empty then it is
/// equivalent (and faster) to call [`Self::draw_text`] instead.
fn draw_text_effects_rgba(
&mut self,
draw: &mut Self::Draw,
Expand Down
36 changes: 17 additions & 19 deletions crates/kas-core/src/theme/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,35 +202,26 @@ impl<'a> DrawCx<'a> {
self.h.selection(rect, style);
}

/// Draw text
///
/// Text is drawn from `rect.pos` and clipped to `rect`. If the text
/// scrolls, `rect` should be the size of the whole text, not the window.
///
/// [`ConfigCx::text_configure`] should be called prior to this method to
/// select a font, font size and wrap options (based on the [`TextClass`]).
pub fn text<T: FormattableText + ?Sized>(&mut self, rect: Rect, text: &Text<T>) {
if let Ok(display) = text.display() {
self.h.text(&self.id, rect, display, text.class());
}
}

/// Draw text with effects
///
/// Text is drawn from `rect.pos` and clipped to `rect`. If the text
/// scrolls, `rect` should be the size of the whole text, not the window.
///
/// [`Self::text`] already supports *font* effects: bold,
/// emphasis, text size. In addition, this method supports underline and
/// strikethrough effects.
/// This method supports a number of text effects: bold, emphasis, text
/// size, underline and strikethrough.
///
/// [`ConfigCx::text_configure`] should be called prior to this method to
/// select a font, font size and wrap options (based on the [`TextClass`]).
pub fn text_effects<T: FormattableText + ?Sized>(&mut self, rect: Rect, text: &Text<T>) {
pub fn text<T: FormattableText + ?Sized>(&mut self, rect: Rect, text: &Text<T>) {
let effects = text.effect_tokens();
let class = text.class();
if let Ok(text) = text.display() {
self.h.text_effects(&self.id, rect, text, effects, class);
if let Ok(display) = text.display() {
if effects.is_empty() {
// Use the faster and simpler implementation when we don't have effects
self.h.text(&self.id, rect, display, class);
} else {
self.h.text_effects(&self.id, rect, display, effects, class);
}
}
}

Expand Down Expand Up @@ -427,6 +418,13 @@ pub trait ThemeDraw {
/// emphasis, text size. In addition, this method supports underline and
/// strikethrough effects.
///
/// If `effects` is empty or all [`Effect::flags`] are default then it is
/// equivalent (and faster) to call [`Self::text`] instead.
///
/// Special effect: if `class` is [`TextClass::AccessLabel(_)`] then
/// underline and strikethrough are only drawn if
/// [`EventState::show_access_labels`].
///
/// [`ConfigCx::text_configure`] should be called prior to this method to
/// select a font, font size and wrap options (based on the [`TextClass`]).
fn text_effects(
Expand Down
11 changes: 0 additions & 11 deletions crates/kas-wgpu/src/draw/text_pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,17 +288,6 @@ impl Window {
effects: &[Effect<()>],
mut draw_quad: impl FnMut(Quad),
) {
// Optimisation: use cheaper TextDisplay::glyphs method
if effects.len() <= 1
&& effects
.first()
.map(|e| e.flags == Default::default())
.unwrap_or(true)
{
self.text(pipe, pass, rect, text, col);
return;
}

let rect = Quad::conv(rect);

let mut for_glyph = |face: FaceId, dpem: f32, glyph: Glyph, _: usize, _: ()| {
Expand Down
6 changes: 1 addition & 5 deletions crates/kas-widgets/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,9 @@ repository = "https://github.com/kas-gui/kas"
exclude = ["/screenshots"]

[package.metadata.docs.rs]
features = ["min_spec", "kas/winit", "kas/wayland"]
features = ["kas/winit", "kas/wayland"]
rustdoc-args = ["--cfg", "docsrs"]

[features]
# Use min_specialization (enables access key underlining for AccessLabel)
min_spec = []

[dependencies]
log = "0.4"
smallvec = "1.6.1"
Expand Down
23 changes: 2 additions & 21 deletions crates/kas-widgets/src/label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,8 @@ impl_scope! {
cx.text_set_size(&mut self.text, rect.size, align);
}

#[cfg(feature = "min_spec")]
default fn draw(&mut self, mut draw: DrawCx) {
draw.text_effects(self.rect(), &self.text);
}
#[cfg(not(feature = "min_spec"))]
fn draw(&mut self, mut draw: DrawCx) {
draw.text_effects(self.rect(), &self.text);
draw.text(self.rect(), &self.text);
}
}

Expand All @@ -155,20 +150,6 @@ impl_scope! {
}
}

// Str/String representations have no effects, so use simpler draw call
#[cfg(feature = "min_spec")]
impl<'a> Layout for Label<&'a str> {
fn draw(&mut self, mut draw: DrawCx) {
draw.text(self.rect(), &self.text);
}
}
#[cfg(feature = "min_spec")]
impl Layout for Label<String> {
fn draw(&mut self, mut draw: DrawCx) {
draw.text(self.rect(), &self.text);
}
}

/* TODO(specialization): can we support this? min_specialization is not enough.
impl<U, T: From<U> + FormattableText + 'static> From<U> for Label<T> {
default fn from(text: U) -> Self {
Expand Down Expand Up @@ -296,7 +277,7 @@ impl_scope! {
}

fn draw(&mut self, mut draw: DrawCx) {
draw.text_effects(self.rect(), &self.text);
draw.text(self.rect(), &self.text);
}
}

Expand Down
1 change: 0 additions & 1 deletion crates/kas-widgets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
//! - [`GripPart`]: a handle (e.g. for a slider, splitter or scroll_bar)

#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg_attr(feature = "min_spec", feature(min_specialization))]

pub mod adapt;
#[doc(no_inline)]
Expand Down
32 changes: 2 additions & 30 deletions crates/kas-widgets/src/scroll_bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,18 +399,6 @@ impl_scope! {
pub fn inner_mut(&mut self) -> &mut W {
&mut self.inner
}

fn draw_(&mut self, mut draw: DrawCx) {
draw.recurse(&mut self.inner);
draw.with_pass(|mut draw| {
if self.show_bars.0 {
draw.recurse(&mut self.horiz_bar);
}
if self.show_bars.1 {
draw.recurse(&mut self.vert_bar);
}
});
}
}

impl HasScrollBars for Self {
Expand Down Expand Up @@ -523,25 +511,9 @@ impl_scope! {
.or_else(|| Some(self.id()))
}

#[cfg(feature = "min_spec")]
default fn draw(&mut self, draw: DrawCx) {
self.draw_(draw);
}
#[cfg(not(feature = "min_spec"))]
fn draw(&mut self, draw: DrawCx) {
self.draw_(draw);
}
}

#[cfg(feature = "min_spec")]
impl<W: Widget> Layout for ScrollBars<ScrollRegion<W>> {
fn draw(&mut self, mut draw: DrawCx) {
// Enlarge clip region to *our* rect:
draw.with_clip_region(self.core.rect, self.inner.scroll_offset(), |mut draw| {
draw.recurse(&mut self.inner);
});
// Use a second clip region to force draw order:
draw.with_clip_region(self.core.rect, Offset::ZERO, |mut draw| {
draw.recurse(&mut self.inner);
draw.with_pass(|mut draw| {
if self.show_bars.0 {
draw.recurse(&mut self.horiz_bar);
}
Expand Down
21 changes: 1 addition & 20 deletions crates/kas-widgets/src/tab_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

use crate::adapt::{AdaptEvents, AdaptWidget};
use crate::{AccessLabel, Row, Stack};
use kas::layout::{FrameStorage, Visitor};
use kas::messages::Select;
use kas::prelude::*;
use kas::theme::FrameStyle;
Expand All @@ -23,13 +22,12 @@ impl_scope! {
#[autoimpl(HasStr using self.label)]
#[widget {
Data = ();
layout = button!(self.label);
layout = frame!(self.label, style = FrameStyle::Tab);
navigable = true;
hover_highlight = true;
}]
pub struct Tab {
core: widget_core!(),
frame: FrameStorage,
#[widget]
label: AccessLabel,
}
Expand All @@ -40,32 +38,15 @@ impl_scope! {
pub fn new(label: impl Into<AccessString>) -> Self {
Tab {
core: Default::default(),
frame: FrameStorage::default(),
label: AccessLabel::new(label),
}
}
}

impl Layout for Self {
fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
let label = Visitor::single(&mut self.label);
Visitor::frame(&mut self.frame, label, FrameStyle::Tab).size_rules(sizer, axis)
}

fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, hints: AlignHints) {
self.core.rect = rect;
let label = Visitor::single(&mut self.label);
Visitor::frame(&mut self.frame, label, FrameStyle::Tab).set_rect(cx, rect, hints)
}

fn find_id(&mut self, coord: Coord) -> Option<Id> {
self.rect().contains(coord).then_some(self.id())
}

fn draw(&mut self, draw: DrawCx) {
let label = Visitor::single(&mut self.label);
Visitor::frame(&mut self.frame, label, FrameStyle::Tab).draw(draw)
}
}

impl Events for Self {
Expand Down
21 changes: 1 addition & 20 deletions crates/kas-widgets/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,8 @@ impl_scope! {
cx.text_set_size(&mut self.text, rect.size, align);
}

#[cfg(feature = "min_spec")]
default fn draw(&mut self, mut draw: DrawCx) {
draw.text_effects(self.rect(), &self.text);
}
#[cfg(not(feature = "min_spec"))]
fn draw(&mut self, mut draw: DrawCx) {
draw.text_effects(self.rect(), &self.text);
draw.text(self.rect(), &self.text);
}
}

Expand All @@ -146,20 +141,6 @@ impl_scope! {
}
}

// Str/String representations have no effects, so use simpler draw call
#[cfg(feature = "min_spec")]
impl<'a, A> Layout for Text<A, &'a str> {
fn draw(&mut self, mut draw: DrawCx) {
draw.text(self.rect(), &self.text);
}
}
#[cfg(feature = "min_spec")]
impl<A> Layout for Text<A, String> {
fn draw(&mut self, mut draw: DrawCx) {
draw.text(self.rect(), &self.text);
}
}

/* TODO(specialization): can we support this? min_specialization is not enough.
impl<U, T: From<U> + FormattableText + 'static> From<U> for Text<T> {
default fn from(text: U) -> Self {
Expand Down
Loading
Loading