Skip to content

Commit

Permalink
Add groove/ridge borders to new border path.
Browse files Browse the repository at this point in the history
  • Loading branch information
gw3583 committed Apr 21, 2017
1 parent 861fb7b commit 910f582
Show file tree
Hide file tree
Showing 14 changed files with 299 additions and 83 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions webrender/res/prim_shared.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ struct Border {

vec4 get_effective_border_widths(Border border) {
switch (int(border.style.x)) {
case BORDER_STYLE_DOUBLE: {
case BORDER_STYLE_DOUBLE:
// Calculate the width of a border segment in a style: double
// border. Round to the nearest CSS pixel.

Expand All @@ -328,10 +328,11 @@ vec4 get_effective_border_widths(Border border) {
// different values in some cases.
// SEE: https://drafts.csswg.org/css-backgrounds-3/#double
return floor(0.5 + border.widths / 3.0);
}
default: {
case BORDER_STYLE_GROOVE:
case BORDER_STYLE_RIDGE:
return floor(0.5 + border.widths * 0.5);
default:
return border.widths;
}
}
}

Expand Down
31 changes: 24 additions & 7 deletions webrender/res/ps_border_corner.fs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ void main(void) {
// Find the appropriate distance to apply the AA smoothstep over.
vec2 fw = fwidth(local_pos);
float afwidth = length(fw);
float distance_for_color;
float color_mix_factor;

// Only apply the clip AA if inside the clip region. This is
// necessary for correctness when the border width is greater
Expand All @@ -97,15 +99,22 @@ void main(void) {
float d2 = distance_to_ellipse(p, vRadii1.xy);
float d3 = distance_to_ellipse(p, vRadii1.zw);

// Signed distance field subtract
float d_outer = max(d0, 0.5 * afwidth - d1);
float d_inner = max(d2, 0.5 * afwidth - d3);
// SDF subtract main radii
float d_main = max(d0, 0.5 * afwidth - d1);

// SDF union
float d = min(d_outer, d_inner);
// SDF subtract inner radii (double style borders)
float d_inner = max(d2 - 0.5 * afwidth, -d3);

// Select how to combine the SDF based on border style.
float d = mix(max(d_main, -d_inner), d_main, vSDFSelect);

// Only apply AA to fragments outside the signed distance field.
alpha = min(alpha, 1.0 - smoothstep(0.0, 0.5 * afwidth, d));

// Get the groove/ridge mix factor.
color_mix_factor = smoothstep(-0.5 * afwidth,
0.5 * afwidth,
-d2);
} else {
// Handle the case where the fragment is outside the clip
// region in a corner. This occurs when border width is
Expand All @@ -123,14 +132,22 @@ void main(void) {
// Select fragment on/off based on signed distance.
// No AA here, since we know we're on a straight edge
// and the width is rounded to a whole CSS pixel.
alpha = min(alpha, mix(0.0, 1.0, d < 0.0));
alpha = min(alpha, mix(vAlphaSelect, 1.0, d < 0.0));

// Get the groove/ridge mix factor.
// TODO(gw): Support AA for groove/ridge border edge with transforms.
color_mix_factor = mix(0.0, 1.0, da > 0.0);
}

// Mix inner/outer color.
vec4 color0 = mix(vColor00, vColor01, color_mix_factor);
vec4 color1 = mix(vColor10, vColor11, color_mix_factor);

// Select color based on side of line. Get distance from the
// reference line, and then apply AA along the edge.
float ld = distance_to_line(vColorEdgeLine.xy, vColorEdgeLine.zw, local_pos);
float m = smoothstep(-0.5 * afwidth, 0.5 * afwidth, ld);
vec4 color = mix(vColor0, vColor1, m);
vec4 color = mix(color0, color1, m);

oFragColor = color * vec4(1.0, 1.0, 1.0, alpha);
}
10 changes: 8 additions & 2 deletions webrender/res/ps_border_corner.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Edge color transition
flat varying vec4 vColor0;
flat varying vec4 vColor1;
flat varying vec4 vColor00;
flat varying vec4 vColor01;
flat varying vec4 vColor10;
flat varying vec4 vColor11;
flat varying vec4 vColorEdgeLine;

// Border radius
Expand All @@ -14,6 +16,10 @@ flat varying vec4 vRadii0;
flat varying vec4 vRadii1;
flat varying vec2 vClipSign;
flat varying vec4 vEdgeDistance;
flat varying float vSDFSelect;

// Border style
flat varying float vAlphaSelect;

#ifdef WR_FEATURE_TRANSFORM
flat varying RectWithSize vLocalRect;
Expand Down
146 changes: 97 additions & 49 deletions webrender/res/ps_border_corner.vs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,36 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

vec4 set_radii(vec2 border_radius,
vec2 border_width,
vec2 invalid_radii) {
vec4 radii;

if (border_radius.x > 0.0 && border_radius.y > 0.0) {
// Set inner/outer radius on valid border radius.
radii.xy = border_radius;
} else {
// No border radius - ensure clip has no effect.
radii.xy = invalid_radii;
vec2 get_radii(vec2 radius, vec2 invalid) {
if (all(greaterThan(radius, vec2(0.0)))) {
return radius;
}

if (all(greaterThan(border_radius, border_width))) {
radii.zw = border_radius - border_width;
} else {
radii.zw = vec2(0.0);
}
return invalid;
}

void set_radii(float style,
vec2 radii,
vec2 widths,
vec2 adjusted_widths) {
vRadii0.xy = get_radii(radii, 2.0 * widths);
vRadii0.zw = get_radii(radii - widths, -widths);

return radii;
switch (int(style)) {
case BORDER_STYLE_RIDGE:
case BORDER_STYLE_GROOVE:
vRadii1.xy = radii - adjusted_widths;
vRadii1.zw = -widths;
break;
case BORDER_STYLE_DOUBLE:
vRadii1.xy = get_radii(radii - adjusted_widths, -widths);
vRadii1.zw = get_radii(radii - widths + adjusted_widths, -widths);
break;
default:
vRadii1.xy = -widths;
vRadii1.zw = -widths;
break;
}
}

void set_edge_line(vec2 border_width,
Expand All @@ -32,6 +42,34 @@ void set_edge_line(vec2 border_width,
vColorEdgeLine = vec4(outer_corner, vec2(-gradient.y, gradient.x));
}

void write_color(vec4 color0, vec4 color1, int style, vec2 delta) {
vec4 modulate;

switch (style) {
case BORDER_STYLE_GROOVE:
modulate = vec4(1.0 - 0.3 * delta.x,
1.0 + 0.3 * delta.x,
1.0 - 0.3 * delta.y,
1.0 + 0.3 * delta.y);

break;
case BORDER_STYLE_RIDGE:
modulate = vec4(1.0 + 0.3 * delta.x,
1.0 - 0.3 * delta.x,
1.0 + 0.3 * delta.y,
1.0 - 0.3 * delta.y);
break;
default:
modulate = vec4(1.0);
break;
}

vColor00 = vec4(color0.rgb * modulate.x, color0.a);
vColor01 = vec4(color0.rgb * modulate.y, color0.a);
vColor10 = vec4(color1.rgb * modulate.z, color1.a);
vColor11 = vec4(color1.rgb * modulate.w, color1.a);
}

void main(void) {
Primitive prim = load_primitive();
Border border = fetch_border(prim.prim_index);
Expand All @@ -46,42 +84,41 @@ void main(void) {
// once we support style transitions per corner.
int style;
vec4 edge_distances;
vec4 color0, color1;
vec2 color_delta;

switch (sub_part) {
case 0: {
p0 = corners.tl_outer;
p1 = corners.tl_inner;
vColor0 = border.colors[0];
vColor1 = border.colors[1];
color0 = border.colors[0];
color1 = border.colors[1];
vClipCenter = corners.tl_outer + border.radii[0].xy;
vClipSign = vec2(1.0);
vRadii0 = set_radii(border.radii[0].xy,
adjusted_widths.xy,
2.0 * border.widths.xy);
vRadii1 = set_radii(border.radii[0].xy - inv_adjusted_widths.xy,
adjusted_widths.xy,
vec2(0.0));
set_radii(border.style.x,
border.radii[0].xy,
border.widths.xy,
adjusted_widths.xy);
set_edge_line(border.widths.xy,
corners.tl_outer,
vec2(1.0, 1.0));
style = int(border.style.x);
edge_distances = vec4(p0 + adjusted_widths.xy,
p0 + inv_adjusted_widths.xy);
color_delta = vec2(1.0);
break;
}
case 1: {
p0 = vec2(corners.tr_inner.x, corners.tr_outer.y);
p1 = vec2(corners.tr_outer.x, corners.tr_inner.y);
vColor0 = border.colors[1];
vColor1 = border.colors[2];
color0 = border.colors[1];
color1 = border.colors[2];
vClipCenter = corners.tr_outer + vec2(-border.radii[0].z, border.radii[0].w);
vClipSign = vec2(-1.0, 1.0);
vRadii0 = set_radii(border.radii[0].zw,
adjusted_widths.zy,
2.0 * border.widths.zy);
vRadii1 = set_radii(border.radii[0].zw - inv_adjusted_widths.zy,
adjusted_widths.zy,
vec2(0.0));
set_radii(border.style.y,
border.radii[0].zw,
border.widths.zy,
adjusted_widths.zy);
set_edge_line(border.widths.zy,
corners.tr_outer,
vec2(-1.0, 1.0));
Expand All @@ -90,21 +127,20 @@ void main(void) {
p0.y + adjusted_widths.y,
p1.x - border.widths.z + adjusted_widths.z,
p0.y + inv_adjusted_widths.y);
color_delta = vec2(1.0, -1.0);
break;
}
case 2: {
p0 = corners.br_inner;
p1 = corners.br_outer;
vColor0 = border.colors[2];
vColor1 = border.colors[3];
color0 = border.colors[2];
color1 = border.colors[3];
vClipCenter = corners.br_outer - border.radii[1].xy;
vClipSign = vec2(-1.0, -1.0);
vRadii0 = set_radii(border.radii[1].xy,
adjusted_widths.zw,
2.0 * border.widths.zw);
vRadii1 = set_radii(border.radii[1].xy - inv_adjusted_widths.zw,
adjusted_widths.zw,
vec2(0.0));
set_radii(border.style.z,
border.radii[1].xy,
border.widths.zw,
adjusted_widths.zw);
set_edge_line(border.widths.zw,
corners.br_outer,
vec2(-1.0, -1.0));
Expand All @@ -113,21 +149,20 @@ void main(void) {
p1.y - adjusted_widths.w,
p1.x - border.widths.z + adjusted_widths.z,
p1.y - border.widths.w + adjusted_widths.w);
color_delta = vec2(-1.0);
break;
}
case 3: {
p0 = vec2(corners.bl_outer.x, corners.bl_inner.y);
p1 = vec2(corners.bl_inner.x, corners.bl_outer.y);
vColor0 = border.colors[3];
vColor1 = border.colors[0];
color0 = border.colors[3];
color1 = border.colors[0];
vClipCenter = corners.bl_outer + vec2(border.radii[1].z, -border.radii[1].w);
vClipSign = vec2(1.0, -1.0);
vRadii0 = set_radii(border.radii[1].zw,
adjusted_widths.xw,
2.0 * border.widths.xw);
vRadii1 = set_radii(border.radii[1].zw - inv_adjusted_widths.xw,
adjusted_widths.xw,
vec2(0.0));
set_radii(border.style.w,
border.radii[1].zw,
border.widths.xw,
adjusted_widths.xw);
set_edge_line(border.widths.xw,
corners.bl_outer,
vec2(1.0, -1.0));
Expand All @@ -136,21 +171,34 @@ void main(void) {
p1.y - adjusted_widths.w,
p0.x + inv_adjusted_widths.x,
p1.y - border.widths.w + adjusted_widths.w);
color_delta = vec2(-1.0, 1.0);
break;
}
}

switch (int(style)) {
case BORDER_STYLE_DOUBLE: {
vEdgeDistance = edge_distances;
vAlphaSelect = 0.0;
vSDFSelect = 0.0;
break;
}
case BORDER_STYLE_GROOVE:
case BORDER_STYLE_RIDGE:
vEdgeDistance = vec4(edge_distances.xy, 0.0, 0.0);
vAlphaSelect = 1.0;
vSDFSelect = 1.0;
break;
default: {
vEdgeDistance = vec4(0.0);
vAlphaSelect = 1.0;
vSDFSelect = 0.0;
break;
}
}

write_color(color0, color1, style, color_delta);

RectWithSize segment_rect;
segment_rect.p0 = p0;
segment_rect.size = p1 - p0;
Expand Down
12 changes: 9 additions & 3 deletions webrender/res/ps_border_edge.fs.glsl
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#line 1

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Expand All @@ -15,7 +17,6 @@ void main(void) {

// Find the appropriate distance to apply the step over.
vec2 fw = fwidth(local_pos);
float afwidth = length(fw);

// Applies the math necessary to draw a style: double
// border. In the case of a solid border, the vertex
Expand All @@ -35,7 +36,12 @@ void main(void) {
// Select fragment on/off based on signed distance.
// No AA here, since we know we're on a straight edge
// and the width is rounded to a whole CSS pixel.
alpha = min(alpha, mix(0.0, 1.0, d < 0.0));
alpha = min(alpha, mix(vAlphaSelect, 1.0, d < 0.0));

// Mix color based on first distance.
// TODO(gw): Support AA for groove/ridge border edge with transforms.
vec4 color = mix(vColor0, vColor1, bvec4(d0 * vEdgeDistance.y > 0.0));

oFragColor = vColor * vec4(1.0, 1.0, 1.0, alpha);
//oFragColor = vec4(d0 * vEdgeDistance.y, -d0 * vEdgeDistance.y, 0, 1.0);
oFragColor = color * vec4(1.0, 1.0, 1.0, alpha);
}
4 changes: 3 additions & 1 deletion webrender/res/ps_border_edge.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

flat varying vec4 vColor;
flat varying vec4 vColor0;
flat varying vec4 vColor1;
flat varying vec2 vEdgeDistance;
flat varying float vAxisSelect;
flat varying float vAlphaSelect;

#ifdef WR_FEATURE_TRANSFORM
varying vec3 vLocalPos;
Expand Down
Loading

0 comments on commit 910f582

Please sign in to comment.