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

Superelliptical shape of corners #16

Merged
merged 1 commit into from
Aug 5, 2022
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: 4 additions & 1 deletion src/effect/rounded-corners-effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const { declarations, code } = loadShader (
class Uniforms {
bounds = 0
clip_radius = 0
smoothing = 0
inner_bounds = 0
inner_clip_radius = 0
pixel_step = 0
Expand Down Expand Up @@ -54,6 +55,7 @@ export default registerClass (
Effect.uniforms = {
bounds: 0,
clip_radius: 0,
smoothing: 0,
inner_bounds: 0,
inner_clip_radius: 0,
pixel_step: 0,
Expand Down Expand Up @@ -123,7 +125,7 @@ export default registerClass (
const border_color = border.color

const radius = corners_cfg.border_radius * scale_factor
const { padding } = corners_cfg
const { padding, smoothing } = corners_cfg

const bounds = [
outer_bounds.x1 + padding.left * scale_factor,
Expand Down Expand Up @@ -152,6 +154,7 @@ export default registerClass (
this.set_uniform_float (location.inner_bounds, 4, inner_bounds)
this.set_uniform_float (location.pixel_step, 2, pixel_step)
this.set_uniform_float (location.border_width, 1, [border_width])
this.set_uniform_float (location.smoothing, 1, [smoothing])
this.set_uniform_float (location.clip_radius, 1, [radius])
this.set_uniform_float (location.border_color, 4, border_color)
this.set_uniform_float (location.inner_clip_radius, 1, [
Expand Down
86 changes: 60 additions & 26 deletions src/effect/shader/rounded_corners.frag
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
// With a litte change to make it works well with windows

// The uniforms variables for controls
// varying vec2 vsPos;

uniform vec4 bounds; // x, y: top left; z, w: bottom right
uniform float clip_radius;
uniform vec4 inner_bounds;
Expand All @@ -14,58 +12,94 @@ uniform vec2 pixel_step;
uniform float skip;
uniform float border_width;
uniform vec4 border_color;
uniform float smoothing;


float circle_bounds(vec2 p, vec2 center, float clip_radius) {
vec2 delta = p - vec2(center.x, center.y);
float dist_squared = dot(delta, delta);

// Fully outside the circle
float outer_radius = clip_radius + 0.5;
if(dist_squared >= (outer_radius * outer_radius))
return 0.0;

// Fully inside the circle
float inner_radius = clip_radius - 0.5;
if(dist_squared <= (inner_radius * inner_radius))
return 1.0;

// Only pixels on the edge of the curve need expensive antialiasing
return outer_radius - sqrt(dist_squared);
}

float squircle_bounds(vec2 p, vec2 center, float clip_radius, float exponent) {
vec2 delta = abs(p - center);

float pow_dx = pow(delta.x, exponent);
float pow_dy = pow(delta.y, exponent);

float dist = pow(pow_dx + pow_dy, 1.0 / exponent);

return clamp(clip_radius - dist + 0.5, 0.0, 1.0);
}

float rounded_rect_coverage(vec2 p, vec4 bounds, float clip_radius) {
float rounded_rect_coverage(vec2 p, vec4 bounds, float clip_radius, float exponent) {
// Outside the bounds
if(p.x < bounds.x || p.x > bounds.z || p.y < bounds.y || p.y > bounds.w) {
return 0.0;
}

vec2 center;

float center_left = bounds.x + clip_radius;
float center_right = bounds.z - clip_radius;
float center_x;

if(p.x < center_left)
center_x = center_left;
center.x = center_left;
else if(p.x > center_right)
center_x = center_right;
center.x = center_right;
else
return 1.0; // The vast majority of pixels exit early here

float center_top = bounds.y + clip_radius;
float center_bottom = bounds.w - clip_radius;
float center_y;

if(p.y < center_top)
center_y = center_top;
center.y = center_top;
else if(p.y > center_bottom)
center_y = center_bottom;
center.y = center_bottom;
else
return 1.0;

if(exponent <= 2.0) {
return circle_bounds(p, center, clip_radius);
} else {
return squircle_bounds(p, center, clip_radius, exponent);
}
}

vec2 delta = p - vec2(center_x, center_y);
float dist_squared = dot(delta, delta);
void main() {
if(skip < 1.0) {

float exponent = smoothing * 10.0 + 2.0;

// Fully outside the circle
float outer_radius = clip_radius + 0.5;
if(dist_squared >= (outer_radius * outer_radius))
return 0.0;
float radius = clip_radius * 0.5 * exponent;

// Fully inside the circle
float inner_radius = clip_radius - 0.5;
if(dist_squared <= (inner_radius * inner_radius))
return 1.0;
float max_radius = min(bounds.z - bounds.x, bounds.w - bounds.y) * 0.5;

// Only pixels on the edge of the curve need expensive antialiasing
return outer_radius - sqrt(dist_squared);
}
if(radius > max_radius) {
exponent *= max_radius / radius;
radius = max_radius;
}

float inner_radius = inner_clip_radius * (radius / clip_radius);

void main() {
if(skip < 1.0) {
vec2 texture_coord = cogl_tex_coord0_in.xy / pixel_step;

float outer_alpha = rounded_rect_coverage(texture_coord, bounds, clip_radius);
float outer_alpha = rounded_rect_coverage(texture_coord, bounds, radius, exponent);
if(border_width > 0.1) {
float inner_alpha = rounded_rect_coverage(texture_coord, inner_bounds, inner_clip_radius);
float inner_alpha = rounded_rect_coverage(texture_coord, inner_bounds, inner_radius, exponent);
float border_alpha = clamp(outer_alpha - inner_alpha, 0.0, 1.0) * cogl_color_out.a;

cogl_color_out = mix(cogl_color_out, vec4(border_color.rgb, 1.0), border_alpha * border_color.a);
Expand Down
5 changes: 5 additions & 0 deletions src/manager/rounded-corners-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,11 @@ export class RoundedCornersManager {
}
const { left, right, top, bottom } = padding

// Increasing border_radius when smoothing is on
if (this.global_rounded_corners !== null) {
border_radius *= 1.0 + this.global_rounded_corners.smoothing
}

// Sadly, the scale of style of St.Widget may be different between scale
// of window if there are two monitor with different scale factor.
// - Scale of Style always as same as primary monitor
Expand Down
5 changes: 5 additions & 0 deletions src/preferences/widgets/rounded-corners-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default GObject.registerClass (
InternalChildren: [
'rounded_in_maximized_switch',
'border_radius_scale',
'smoothing_scale',
'padding_left_scale',
'padding_right_scale',
'padding_top_scale',
Expand All @@ -28,6 +29,7 @@ export default GObject.registerClass (
class extends Gtk.ListBox {
private _rounded_in_maximized_switch !: Gtk.Switch
private _border_radius_scale !: Gtk.Scale
private _smoothing_scale !: Gtk.Scale
private _padding_left_scale !: Gtk.Scale
private _padding_right_scale !: Gtk.Scale
private _padding_top_scale !: Gtk.Scale
Expand All @@ -43,6 +45,7 @@ export default GObject.registerClass (
super._init ()
this._scales = [
this._border_radius_scale,
this._smoothing_scale,
this._padding_bottom_scale,
this._padding_left_scale,
this._padding_right_scale,
Expand Down Expand Up @@ -90,13 +93,15 @@ export default GObject.registerClass (
},
keep_rounded_corners: this._rounded_in_maximized_switch.active,
border_radius: this._border_radius_scale.get_value (),
smoothing: this._smoothing_scale.get_value (),
enabled: true,
}
}

set cfg (cfg: RoundedCornersCfg) {
this._rounded_in_maximized_switch.active = cfg.keep_rounded_corners
this._border_radius_scale.set_value (cfg.border_radius)
this._smoothing_scale.set_value (cfg.smoothing)
this._padding_left_scale.set_value (cfg.padding.left)
this._padding_right_scale.set_value (cfg.padding.right)
this._padding_top_scale.set_value (cfg.padding.top)
Expand Down
40 changes: 40 additions & 0 deletions src/preferences/widgets/rounded-corners-item.ui
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,40 @@
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="name">Don't Configuration in Custom Page</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkBox">
<property name="valign">center</property>
<property name="hexpand">true</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="halign">start</property>
<property name="label" translatable="yes">Corner Smoothing</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScale" id="smoothing_scale">
<property name="visible">true</property>
<property name="valign">center</property>
<property name="width-request">280</property>
<property name="draw-value">true</property>
<property name="round-digits">1</property>
<property name="orientation">horizontal</property>
<property name="adjustment">smoothing_ajustment</property>
<property name="value-pos">right</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<child>
Expand Down Expand Up @@ -270,6 +304,12 @@
<property name="upper">40</property>
<property name="page-increment">1</property>
<property name="step-increment">1</property>
</object>
<object class="GtkAdjustment" id="smoothing_ajustment">
<property name="lower">0</property>
<property name="upper">1</property>
<property name="page-increment">0.1</property>
<property name="step-increment">0.1</property>
</object>
<object class="GtkAdjustment" id="padding_left_ajustment">
<property name="lower">0</property>
Expand Down
1 change: 1 addition & 0 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export class Padding {
export interface RoundedCornersCfg {
keep_rounded_corners: boolean
border_radius: number
smoothing: number
padding: Padding
enabled: boolean
}
Expand Down