Source code
Revision control
Copy as Markdown
Other Tools
/* 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
#include shared,rect,ellipse
#define DONT_MIX 0
#define MIX_AA 1
#define MIX_NO_AA 2
// For edges, the colors are the same. For corners, these
// are the colors of each edge making up the corner.
flat varying mediump vec4 vColor0;
flat varying mediump vec4 vColor1;
// A point + tangent defining the line where the edge
// transition occurs. Used for corners only.
flat varying highp vec4 vColorLine;
// A boolean indicating that we should be mixing between edge colors.
flat varying mediump ivec2 vMixColors;
// xy = Local space position of the clip center.
// zw = Scale the rect origin by this to get the outer
// corner from the segment rectangle.
flat varying highp vec4 vClipCenter_Sign;
// An outer and inner elliptical radii for border
// corner clipping.
flat varying highp vec4 vClipRadii;
// Position, scale, and radii of horizontally and vertically adjacent corner clips.
flat varying highp vec4 vHorizontalClipCenter_Sign;
flat varying highp vec2 vHorizontalClipRadii;
flat varying highp vec4 vVerticalClipCenter_Sign;
flat varying highp vec2 vVerticalClipRadii;
// Local space position
varying highp vec2 vPos;
#define SEGMENT_TOP_LEFT 0
#define SEGMENT_TOP_RIGHT 1
#define SEGMENT_BOTTOM_RIGHT 2
#define SEGMENT_BOTTOM_LEFT 3
#ifdef WR_VERTEX_SHADER
PER_INSTANCE in vec2 aTaskOrigin;
PER_INSTANCE in vec4 aRect;
PER_INSTANCE in vec4 aColor0;
PER_INSTANCE in vec4 aColor1;
PER_INSTANCE in int aFlags;
PER_INSTANCE in vec2 aWidths;
PER_INSTANCE in vec2 aRadii;
PER_INSTANCE in vec4 aClipParams1;
PER_INSTANCE in vec4 aClipParams2;
vec2 get_outer_corner_scale(int segment) {
vec2 p;
switch (segment) {
case SEGMENT_TOP_LEFT:
p = vec2(0.0, 0.0);
break;
case SEGMENT_TOP_RIGHT:
p = vec2(1.0, 0.0);
break;
case SEGMENT_BOTTOM_RIGHT:
p = vec2(1.0, 1.0);
break;
case SEGMENT_BOTTOM_LEFT:
p = vec2(0.0, 1.0);
break;
default:
// The result is only used for non-default segment cases
p = vec2(0.0);
break;
}
return p;
}
void main(void) {
int segment = aFlags & 0xff;
bool do_aa = ((aFlags >> 24) & 0xf0) != 0;
vec2 outer_scale = get_outer_corner_scale(segment);
vec2 size = aRect.zw - aRect.xy;
vec2 outer = outer_scale * size;
vec2 clip_sign = 1.0 - 2.0 * outer_scale;
int mix_colors;
switch (segment) {
case SEGMENT_TOP_LEFT:
case SEGMENT_TOP_RIGHT:
case SEGMENT_BOTTOM_RIGHT:
case SEGMENT_BOTTOM_LEFT: {
mix_colors = do_aa ? MIX_AA : MIX_NO_AA;
break;
}
default:
mix_colors = DONT_MIX;
break;
}
vMixColors.x = mix_colors;
vPos = size * aPosition.xy;
vColor0 = aColor0;
vColor1 = aColor1;
vClipCenter_Sign = vec4(outer + clip_sign * aRadii, clip_sign);
vClipRadii = vec4(aRadii, max(aRadii - aWidths, 0.0));
vColorLine = vec4(outer, aWidths.y * -clip_sign.y, aWidths.x * clip_sign.x);
vec2 horizontal_clip_sign = vec2(-clip_sign.x, clip_sign.y);
vHorizontalClipCenter_Sign = vec4(aClipParams1.xy +
horizontal_clip_sign * aClipParams1.zw,
horizontal_clip_sign);
vHorizontalClipRadii = aClipParams1.zw;
vec2 vertical_clip_sign = vec2(clip_sign.x, -clip_sign.y);
vVerticalClipCenter_Sign = vec4(aClipParams2.xy +
vertical_clip_sign * aClipParams2.zw,
vertical_clip_sign);
vVerticalClipRadii = aClipParams2.zw;
gl_Position = uTransform * vec4(aTaskOrigin + aRect.xy + vPos, 0.0, 1.0);
}
#endif
#ifdef WR_FRAGMENT_SHADER
void main(void) {
float aa_range = compute_aa_range(vPos);
bool do_aa = vMixColors.x != MIX_NO_AA;
float mix_factor = 0.0;
if (vMixColors.x != DONT_MIX) {
float d_line = distance_to_line(vColorLine.xy, vColorLine.zw, vPos);
if (do_aa) {
mix_factor = distance_aa(aa_range, -d_line);
} else {
mix_factor = d_line + EPSILON >= 0. ? 1.0 : 0.0;
}
}
// Check if inside main corner clip-region
vec2 clip_relative_pos = vPos - vClipCenter_Sign.xy;
bool in_clip_region = all(lessThan(vClipCenter_Sign.zw * clip_relative_pos, vec2(0.0)));
float d = -1.0;
if (in_clip_region) {
float d_radii_a = distance_to_ellipse(clip_relative_pos, vClipRadii.xy);
float d_radii_b = distance_to_ellipse(clip_relative_pos, vClipRadii.zw);
d = max(d_radii_a, -d_radii_b);
}
// And again for horizontally-adjacent corner
clip_relative_pos = vPos - vHorizontalClipCenter_Sign.xy;
in_clip_region = all(lessThan(vHorizontalClipCenter_Sign.zw * clip_relative_pos, vec2(0.0)));
if (in_clip_region) {
float d_radii = distance_to_ellipse(clip_relative_pos, vHorizontalClipRadii.xy);
d = max(d_radii, d);
}
// And finally for vertically-adjacent corner
clip_relative_pos = vPos - vVerticalClipCenter_Sign.xy;
in_clip_region = all(lessThan(vVerticalClipCenter_Sign.zw * clip_relative_pos, vec2(0.0)));
if (in_clip_region) {
float d_radii = distance_to_ellipse(clip_relative_pos, vVerticalClipRadii.xy);
d = max(d_radii, d);
}
float alpha = do_aa ? distance_aa(aa_range, d) : 1.0;
vec4 color = mix(vColor0, vColor1, mix_factor);
oFragColor = color * alpha;
}
#endif