cs_line_decoration.glsl (5861B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include shared 6 7 #define LINE_STYLE_SOLID 0 8 #define LINE_STYLE_DOTTED 1 9 #define LINE_STYLE_DASHED 2 10 #define LINE_STYLE_WAVY 3 11 12 // Fragment position in the coordinate system used for positioning decorations. 13 // To keep the code independent of whether the line is horizontal or vertical, 14 // vLocalPos.x is always parallel, and .y always perpendicular, to the line 15 // being decorated. 16 varying highp vec2 vLocalPos; 17 18 // Line style. Packed in to a vector to work around bug 1630356. 19 flat varying mediump ivec2 vStyle; 20 21 flat varying mediump vec4 vParams; 22 23 #ifdef WR_VERTEX_SHADER 24 25 // The size of the mask tile we're rendering, in pixels. 26 PER_INSTANCE in vec4 aTaskRect; 27 28 // The size of the mask tile. aLocalSize.x is always horizontal and .y vertical, 29 // regardless of the line's orientation. The size is chosen by 30 // prim_store::line_dec::get_line_decoration_sizes. 31 PER_INSTANCE in vec2 aLocalSize; 32 33 // A LINE_STYLE_* value, indicating what sort of line to draw. 34 PER_INSTANCE in int aStyle; 35 36 // 0.0 for a horizontal line, 1.0 for a vertical line. 37 PER_INSTANCE in float aAxisSelect; 38 39 // The thickness of the wavy line itself, not the amplitude of the waves (i.e., 40 // the thickness of the final decorated line). 41 PER_INSTANCE in float aWavyLineThickness; 42 43 void main(void) { 44 vec2 size = mix(aLocalSize, aLocalSize.yx, aAxisSelect); 45 vStyle.x = aStyle; 46 47 switch (vStyle.x) { 48 case LINE_STYLE_SOLID: { 49 break; 50 } 51 case LINE_STYLE_DASHED: { 52 vParams = vec4(size.x, // period 53 0.5 * size.x, // dash length 54 0.0, 55 0.0); 56 break; 57 } 58 case LINE_STYLE_DOTTED: { 59 float diameter = size.y; 60 float period = diameter * 2.0; 61 float center_line = 0.5 * size.y; 62 vParams = vec4(period, 63 diameter / 2.0, // radius 64 center_line, 65 0.0); 66 break; 67 } 68 case LINE_STYLE_WAVY: { 69 // This logic copied from gecko to get the same results 70 float line_thickness = max(aWavyLineThickness, 1.0); 71 // Difference in height between peaks and troughs 72 // (and since slopes are 45 degrees, the length of each slope) 73 float slope_length = size.y - line_thickness; 74 // Length of flat runs 75 float flat_length = max((line_thickness - 1.0) * 2.0, 1.0); 76 77 vParams = vec4(line_thickness / 2.0, 78 slope_length, 79 flat_length, 80 size.y); 81 break; 82 } 83 default: 84 vParams = vec4(0.0); 85 } 86 87 vLocalPos = mix(aPosition.xy, aPosition.yx, aAxisSelect) * size; 88 89 gl_Position = uTransform * vec4(mix(aTaskRect.xy, aTaskRect.zw, aPosition.xy), 0.0, 1.0); 90 } 91 #endif 92 93 #ifdef WR_FRAGMENT_SHADER 94 95 #define MAGIC_WAVY_LINE_AA_SNAP 0.5 96 97 void main(void) { 98 // Find the appropriate distance to apply the step over. 99 vec2 pos = vLocalPos; 100 float aa_range = compute_aa_range(pos); 101 float alpha = 1.0; 102 103 switch (vStyle.x) { 104 case LINE_STYLE_SOLID: { 105 break; 106 } 107 case LINE_STYLE_DASHED: { 108 // Calculate dash alpha (on/off) based on dash length 109 alpha = step(floor(pos.x + 0.5), vParams.y); 110 break; 111 } 112 case LINE_STYLE_DOTTED: { 113 // Get the dot alpha 114 vec2 dot_relative_pos = pos - vParams.yz; 115 float dot_distance = length(dot_relative_pos) - vParams.y; 116 alpha = distance_aa(aa_range, dot_distance); 117 break; 118 } 119 case LINE_STYLE_WAVY: { 120 float half_line_thickness = vParams.x; 121 float slope_length = vParams.y; 122 float flat_length = vParams.z; 123 float vertical_bounds = vParams.w; 124 // Our pattern is just two slopes and two flats 125 float half_period = slope_length + flat_length; 126 127 float mid_height = vertical_bounds / 2.0; 128 float peak_offset = mid_height - half_line_thickness; 129 // Flip the wave every half period 130 float flip = -2.0 * (step(mod(pos.x, 2.0 * half_period), half_period) - 0.5); 131 // float flip = -1.0; 132 peak_offset *= flip; 133 float peak_height = mid_height + peak_offset; 134 135 // Convert pos to a local position within one half period 136 pos.x = mod(pos.x, half_period); 137 138 // Compute signed distance to the 3 lines that make up an arc 139 float dist1 = distance_to_line(vec2(0.0, peak_height), 140 vec2(1.0, -flip), 141 pos); 142 float dist2 = distance_to_line(vec2(0.0, peak_height), 143 vec2(0, -flip), 144 pos); 145 float dist3 = distance_to_line(vec2(flat_length, peak_height), 146 vec2(-1.0, -flip), 147 pos); 148 float dist = abs(max(max(dist1, dist2), dist3)); 149 150 // Apply AA based on the thickness of the wave 151 alpha = distance_aa(aa_range, dist - half_line_thickness); 152 153 // Disable AA for thin lines 154 if (half_line_thickness <= 1.0) { 155 alpha = 1.0 - step(alpha, MAGIC_WAVY_LINE_AA_SNAP); 156 } 157 158 break; 159 } 160 default: break; 161 } 162 163 oFragColor = vec4(alpha); 164 } 165 #endif