mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-29 06:51:10 +00:00
369 lines
9.1 KiB
GLSL
369 lines
9.1 KiB
GLSL
#ifndef _PATTERN_
|
|
#define _PATTERN_
|
|
|
|
#include "common.glsl"
|
|
#include "gradient.glsl"
|
|
#include "rect.glsl"
|
|
|
|
#ifdef GSK_FRAGMENT_SHADER
|
|
|
|
vec4 stack[GSK_GPU_PATTERN_STACK_SIZE];
|
|
uint stack_size = 0u;
|
|
|
|
void
|
|
stack_push (vec4 data)
|
|
{
|
|
stack[stack_size] = data;
|
|
stack_size++;
|
|
}
|
|
|
|
vec4
|
|
stack_pop (void)
|
|
{
|
|
stack_size--;
|
|
return stack[stack_size];
|
|
}
|
|
|
|
uint
|
|
read_uint (inout uint reader)
|
|
{
|
|
uint result = gsk_get_uint (reader);
|
|
reader++;
|
|
return result;
|
|
}
|
|
|
|
float
|
|
read_float (inout uint reader)
|
|
{
|
|
float result = gsk_get_float (reader);
|
|
reader++;
|
|
return result;
|
|
}
|
|
|
|
vec2
|
|
read_vec2 (inout uint reader)
|
|
{
|
|
return vec2 (read_float (reader), read_float (reader));
|
|
}
|
|
|
|
vec4
|
|
read_vec4 (inout uint reader)
|
|
{
|
|
return vec4 (read_float (reader), read_float (reader), read_float (reader), read_float (reader));
|
|
}
|
|
|
|
Rect
|
|
read_rect (inout uint reader)
|
|
{
|
|
return rect_from_gsk (read_vec4 (reader));
|
|
}
|
|
|
|
mat4
|
|
read_mat4 (inout uint reader)
|
|
{
|
|
mat4 result = mat4 (gsk_get_float (reader + 0u), gsk_get_float (reader + 1u),
|
|
gsk_get_float (reader + 2u), gsk_get_float (reader + 3u),
|
|
gsk_get_float (reader + 4u), gsk_get_float (reader + 5u),
|
|
gsk_get_float (reader + 6u), gsk_get_float (reader + 7u),
|
|
gsk_get_float (reader + 8u), gsk_get_float (reader + 9u),
|
|
gsk_get_float (reader + 10u), gsk_get_float (reader + 11u),
|
|
gsk_get_float (reader + 12u), gsk_get_float (reader + 13u),
|
|
gsk_get_float (reader + 14u), gsk_get_float (reader + 15u));
|
|
reader += 16u;
|
|
return result;
|
|
}
|
|
|
|
Gradient
|
|
read_gradient (inout uint reader)
|
|
{
|
|
Gradient gradient = gradient_new (reader);
|
|
reader += gradient_get_size (gradient);
|
|
|
|
return gradient;
|
|
}
|
|
|
|
void
|
|
clip_pattern (inout uint reader,
|
|
inout vec4 color,
|
|
vec2 pos)
|
|
{
|
|
Rect clip = read_rect (reader);
|
|
float alpha = rect_coverage (clip, pos);
|
|
|
|
color *= alpha;
|
|
}
|
|
|
|
void
|
|
opacity_pattern (inout uint reader,
|
|
inout vec4 color,
|
|
vec2 pos)
|
|
{
|
|
float opacity = read_float (reader);
|
|
|
|
color *= opacity;
|
|
}
|
|
|
|
void
|
|
color_matrix_pattern (inout uint reader,
|
|
inout vec4 color,
|
|
vec2 pos)
|
|
{
|
|
mat4 matrix = read_mat4 (reader);
|
|
vec4 offset = read_vec4 (reader);
|
|
|
|
color = color_unpremultiply (color);
|
|
|
|
color = matrix * color + offset;
|
|
color = clamp(color, 0.0, 1.0);
|
|
|
|
color = color_premultiply (color);
|
|
}
|
|
|
|
void
|
|
repeat_push_pattern (inout uint reader,
|
|
inout vec2 pos)
|
|
{
|
|
stack_push (vec4 (pos, 0.0, 0.0));
|
|
Rect bounds = read_rect (reader);
|
|
|
|
vec2 size = rect_size (bounds);
|
|
pos = mod (pos - bounds.bounds.xy, size);
|
|
/* make sure we have a positive result */
|
|
pos = mix (pos, pos + size, lessThan (pos, vec2 (0.0)));
|
|
pos += bounds.bounds.xy;
|
|
}
|
|
|
|
void
|
|
position_pop_pattern (inout uint reader,
|
|
inout vec2 pos)
|
|
{
|
|
pos = stack_pop ().xy;
|
|
}
|
|
|
|
void
|
|
cross_fade_pattern (inout uint reader,
|
|
inout vec4 color)
|
|
{
|
|
vec4 start = stack_pop ();
|
|
float progress = read_float (reader);
|
|
|
|
color = mix (start, color, progress);
|
|
}
|
|
|
|
void
|
|
mask_alpha_pattern (inout uint reader,
|
|
inout vec4 color)
|
|
{
|
|
vec4 source = stack_pop ();
|
|
|
|
color = source * color.a;
|
|
}
|
|
|
|
void
|
|
mask_inverted_alpha_pattern (inout uint reader,
|
|
inout vec4 color)
|
|
{
|
|
vec4 source = stack_pop ();
|
|
|
|
color = source * (1.0 - color.a);
|
|
}
|
|
|
|
void
|
|
mask_luminance_pattern (inout uint reader,
|
|
inout vec4 color)
|
|
{
|
|
vec4 source = stack_pop ();
|
|
|
|
color = source * luminance (color.rgb);
|
|
}
|
|
|
|
void
|
|
mask_inverted_luminance_pattern (inout uint reader,
|
|
inout vec4 color)
|
|
{
|
|
vec4 source = stack_pop ();
|
|
|
|
color = source * (color.a - luminance (color.rgb));
|
|
}
|
|
|
|
vec4
|
|
glyphs_pattern (inout uint reader,
|
|
vec2 pos)
|
|
{
|
|
float opacity = 0.0;
|
|
vec4 color = color_premultiply (read_vec4 (reader));
|
|
uint num_glyphs = read_uint (reader);
|
|
uint i;
|
|
|
|
for (i = 0u; i < num_glyphs; i++)
|
|
{
|
|
uint tex_id = read_uint (reader);
|
|
Rect glyph_bounds = read_rect (reader);
|
|
vec4 tex_rect = read_vec4 (reader);
|
|
|
|
float coverage = rect_coverage (glyph_bounds, pos);
|
|
if (coverage > 0.0)
|
|
opacity += coverage * gsk_texture (tex_id, (pos - push.scale * tex_rect.xy) / (push.scale * tex_rect.zw)).a;
|
|
}
|
|
|
|
return color * opacity;
|
|
}
|
|
|
|
vec4
|
|
texture_pattern (inout uint reader,
|
|
vec2 pos)
|
|
{
|
|
uint tex_id = read_uint (reader);
|
|
vec4 tex_rect = read_vec4 (reader);
|
|
|
|
return gsk_texture (tex_id, (pos - push.scale * tex_rect.xy) / (push.scale * tex_rect.zw));
|
|
}
|
|
|
|
vec4
|
|
linear_gradient_pattern (inout uint reader,
|
|
vec2 pos,
|
|
bool repeating)
|
|
{
|
|
vec2 start = read_vec2 (reader) * push.scale;
|
|
vec2 end = read_vec2 (reader) * push.scale;
|
|
Gradient gradient = read_gradient (reader);
|
|
|
|
vec2 line = end - start;
|
|
float line_length = dot (line, line);
|
|
float offset = dot (pos - start, line) / line_length;
|
|
float d_offset = 0.5 * fwidth (offset);
|
|
|
|
if (repeating)
|
|
return gradient_get_color_repeating (gradient, offset - d_offset, offset + d_offset);
|
|
else
|
|
return gradient_get_color (gradient, offset - d_offset, offset + d_offset);
|
|
}
|
|
|
|
vec4
|
|
radial_gradient_pattern (inout uint reader,
|
|
vec2 pos,
|
|
bool repeating)
|
|
{
|
|
vec2 center = read_vec2 (reader) * push.scale;
|
|
vec2 radius = read_vec2 (reader) * push.scale;
|
|
float start = read_float (reader);
|
|
float end = read_float (reader);
|
|
Gradient gradient = read_gradient (reader);
|
|
|
|
float offset = length ((pos - center) / radius);
|
|
offset = (offset - start) / (end - start);
|
|
float d_offset = 0.5 * fwidth (offset);
|
|
|
|
if (repeating)
|
|
return gradient_get_color_repeating (gradient, offset - d_offset, offset + d_offset);
|
|
else
|
|
return gradient_get_color (gradient, offset - d_offset, offset + d_offset);
|
|
}
|
|
|
|
vec4
|
|
conic_gradient_pattern (inout uint reader,
|
|
vec2 pos)
|
|
{
|
|
vec2 center = read_vec2 (reader);
|
|
float angle = read_float (reader);
|
|
Gradient gradient = read_gradient (reader);
|
|
|
|
/* scaling modifies angles, so be sure to use right coordinate system */
|
|
pos = pos / push.scale - center;
|
|
float offset = atan (pos.y, pos.x);
|
|
offset = degrees (offset + angle) / 360.0;
|
|
float overflow = fract (offset + 0.5);
|
|
offset = fract (offset);
|
|
float d_offset = max (0.00001, 0.5 * min (fwidth (offset), fwidth (overflow)));
|
|
|
|
return gradient_get_color_repeating (gradient, offset - d_offset, offset + d_offset);
|
|
}
|
|
|
|
vec4
|
|
color_pattern (inout uint reader)
|
|
{
|
|
vec4 color = read_vec4 (reader);
|
|
|
|
return color_premultiply (color);
|
|
}
|
|
|
|
vec4
|
|
pattern (uint reader,
|
|
vec2 pos)
|
|
{
|
|
vec4 color = vec4 (1.0, 0.0, 0.8, 1.0); /* pink */
|
|
|
|
for(;;)
|
|
{
|
|
uint type = read_uint (reader);
|
|
switch (type)
|
|
{
|
|
default:
|
|
case GSK_GPU_PATTERN_DONE:
|
|
return color;
|
|
case GSK_GPU_PATTERN_COLOR:
|
|
color = color_pattern (reader);
|
|
break;
|
|
case GSK_GPU_PATTERN_TEXTURE:
|
|
color = texture_pattern (reader, pos);
|
|
break;
|
|
case GSK_GPU_PATTERN_GLYPHS:
|
|
color = glyphs_pattern (reader, pos);
|
|
break;
|
|
case GSK_GPU_PATTERN_COLOR_MATRIX:
|
|
color_matrix_pattern (reader, color, pos);
|
|
break;
|
|
case GSK_GPU_PATTERN_OPACITY:
|
|
opacity_pattern (reader, color, pos);
|
|
break;
|
|
case GSK_GPU_PATTERN_LINEAR_GRADIENT:
|
|
color = linear_gradient_pattern (reader, pos, false);
|
|
break;
|
|
case GSK_GPU_PATTERN_REPEATING_LINEAR_GRADIENT:
|
|
color = linear_gradient_pattern (reader, pos, true);
|
|
break;
|
|
case GSK_GPU_PATTERN_RADIAL_GRADIENT:
|
|
color = radial_gradient_pattern (reader, pos, false);
|
|
break;
|
|
case GSK_GPU_PATTERN_REPEATING_RADIAL_GRADIENT:
|
|
color = radial_gradient_pattern (reader, pos, true);
|
|
break;
|
|
case GSK_GPU_PATTERN_CONIC_GRADIENT:
|
|
color = conic_gradient_pattern (reader, pos);
|
|
break;
|
|
case GSK_GPU_PATTERN_CLIP:
|
|
clip_pattern (reader, color, pos);
|
|
break;
|
|
case GSK_GPU_PATTERN_REPEAT_PUSH:
|
|
repeat_push_pattern (reader, pos);
|
|
break;
|
|
case GSK_GPU_PATTERN_POSITION_POP:
|
|
position_pop_pattern (reader, pos);
|
|
break;
|
|
case GSK_GPU_PATTERN_PUSH_COLOR:
|
|
stack_push (color);
|
|
color = vec4 (0.0);
|
|
break;
|
|
case GSK_GPU_PATTERN_POP_CROSS_FADE:
|
|
cross_fade_pattern (reader, color);
|
|
break;
|
|
case GSK_GPU_PATTERN_POP_MASK_ALPHA:
|
|
mask_alpha_pattern (reader, color);
|
|
break;
|
|
case GSK_GPU_PATTERN_POP_MASK_INVERTED_ALPHA:
|
|
mask_inverted_alpha_pattern (reader, color);
|
|
break;
|
|
case GSK_GPU_PATTERN_POP_MASK_LUMINANCE:
|
|
mask_luminance_pattern (reader, color);
|
|
break;
|
|
case GSK_GPU_PATTERN_POP_MASK_INVERTED_LUMINANCE:
|
|
mask_inverted_luminance_pattern (reader, color);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|