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

rewrite push_line interface, and make patterned lines match gecko closer #1923

Merged
merged 4 commits into from Oct 25, 2017
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

rewrite push_line interface, and make wavy lines match gecko closer

This is a breaking API change, as it replaces the (gross) (baseline,start,end,width)
API with just using the line's bounds. This also adds a dedicated value for wavy
line thickness, as there isn't a 1:1 function between the two in gecko.

Wavy lines are changed to have the same period as gecko uses, which is necessary
to make some subtle hacks where gecko aligns and clips multiple lines to make
the illusion of a single continuous line.

Wavy lines are also changed to not have AA if they are thin (thickness <= 2.0),
as this matches the standard gecko style.

Future work needs to be done to make dashed and dotted lines also support
this continuity illusion (but no API/gecko work should need to be done).
  • Loading branch information
Gankra committed Oct 24, 2017
commit 978f23424fe2c7be663b131973c858358460f455
@@ -22,13 +22,14 @@ varying vec2 vLocalPos;

struct Line {
vec4 color;
float wavyLineThickness;
float style;
float orientation;
};

Line fetch_line(int address) {
vec4 data[2] = fetch_from_resource_cache_2(address);
return Line(data[0], data[1].x, data[1].y);
return Line(data[0], data[1].x, data[1].y, data[1].z);
}

void main(void) {
@@ -85,14 +86,18 @@ void main(void) {
break;
}
case LINE_STYLE_WAVY: {
// Choose some arbitrary values to scale thickness,
// wave period etc.
// TODO(gw): Tune these to get closer to what Gecko uses.
float thickness = 0.15 * size.y;
vParams = vec4(thickness,
size.y * 0.5,
size.y * 0.75,
size.y * 0.5);
// This logic copied from gecko to get the same results
float line_thickness = max(line.wavyLineThickness, 1.0);
// Difference in height between peaks and troughs
// (and since slopes are 45 degrees, the length of each slope)
float slope_length = size.y - line_thickness;
// Length of flat runs
float flat_length = max((line_thickness - 1.0) * 2.0, 1.0);

vParams = vec4(line_thickness / 2.0,
slope_length,
flat_length,
size.y);
break;
}
}
@@ -142,6 +147,9 @@ void main(void) {
#endif

#ifdef WR_FRAGMENT_SHADER

#define MAGIC_WAVY_LINE_AA_SNAP 0.7

float det(vec2 a, vec2 b) {
return a.x * b.y - b.x * a.y;
}
@@ -220,35 +228,44 @@ void main(void) {
case LINE_STYLE_WAVY: {
vec2 normalized_local_pos = pos - vLocalOrigin.xy;

float y0 = vParams.y;
float dy = vParams.z;
float dx = vParams.w;

// Flip the position of the bezier center points each
// wave period.
dy *= step(mod(normalized_local_pos.x, 4.0 * dx), 2.0 * dx) * 2.0 - 1.0;

// Convert pos to a local position within one wave period.
normalized_local_pos.x = dx + mod(normalized_local_pos.x, 2.0 * dx);

// Evaluate SDF to the first bezier.
vec2 b0_0 = vec2(0.0 * dx, y0);
vec2 b1_0 = vec2(1.0 * dx, y0 - dy);
vec2 b2_0 = vec2(2.0 * dx, y0);
float d1 = approx_distance(normalized_local_pos, b0_0, b1_0, b2_0);

// Evaluate SDF to the second bezier.
vec2 b0_1 = vec2(2.0 * dx, y0);
vec2 b1_1 = vec2(3.0 * dx, y0 + dy);
vec2 b2_1 = vec2(4.0 * dx, y0);
float d2 = approx_distance(normalized_local_pos, b0_1, b1_1, b2_1);

// SDF union - this is needed to avoid artifacts where the
// bezier curves join.
float d = min(d1, d2);
float half_line_thickness = vParams.x;
float slope_length = vParams.y;
float flat_length = vParams.z;
float vertical_bounds = vParams.w;
// Our pattern is just two slopes and two flats
float half_period = slope_length + flat_length;

float mid_height = vertical_bounds / 2.0;
float peak_offset = mid_height - half_line_thickness;
// Flip the wave every half period
float flip = -2.0 * (step(mod(normalized_local_pos.x, 2.0 * half_period), half_period) - 0.5);
// float flip = -1.0;
peak_offset *= flip;
float peak_height = mid_height + peak_offset;

// Convert pos to a local position within one half period
normalized_local_pos.x = mod(normalized_local_pos.x, half_period);

// Compute signed distance to the 3 lines that make up an arc
float dist1 = distance_to_line(vec2(0.0, peak_height),
vec2(1.0, -flip),
normalized_local_pos);
float dist2 = distance_to_line(vec2(0.0, peak_height),
vec2(0, -flip),
normalized_local_pos);
float dist3 = distance_to_line(vec2(flat_length, peak_height),
vec2(-1.0, -flip),
normalized_local_pos);
float dist = abs(max(max(dist1, dist2), dist3));

// Apply AA based on the thickness of the wave
alpha = distance_aa(aa_range, dist - half_line_thickness);

// Disable AA for thin lines
if (half_line_thickness <= 1.0) {
alpha = 1.0 - step(alpha, MAGIC_WAVY_LINE_AA_SNAP);
}

// Apply AA based on the thickness of the wave.
alpha = distance_aa(aa_range, d - vParams.x);
break;
}
}
@@ -518,21 +518,11 @@ impl FrameContext {
}
}
SpecificDisplayItem::Line(ref info) => {
let prim_info = LayerPrimitiveInfo {
rect: LayerRect::zero(),
local_clip: *item.local_clip(),
is_backface_visible: prim_info.is_backface_visible,
tag: prim_info.tag,
};

context.builder.add_line(
clip_and_scroll,
&prim_info,
info.baseline,
info.start,
info.end,
info.wavy_line_thickness,
info.orientation,
info.width,
&info.color,
info.style,
);
@@ -651,26 +651,13 @@ impl FrameBuilder {
&mut self,
clip_and_scroll: ClipAndScrollInfo,
info: &LayerPrimitiveInfo,
baseline: f32,
start: f32,
end: f32,
wavy_line_thickness: f32,
orientation: LineOrientation,
width: f32,
color: &ColorF,
style: LineStyle,
) {
let new_rect = match orientation {
LineOrientation::Horizontal => LayerRect::new(
LayerPoint::new(start, baseline),
LayerSize::new(end - start, width),
),
LineOrientation::Vertical => LayerRect::new(
LayerPoint::new(baseline, start),
LayerSize::new(width, end - start),
),
};

let line = LinePrimitive {
wavy_line_thickness,
color: *color,
style: style,
orientation: orientation,
@@ -690,7 +677,7 @@ impl FrameBuilder {
let mut line = line.clone();
line.color = shadow.color;
let mut info = info.clone();
info.rect = new_rect.translate(&shadow.offset);
info.rect = info.rect.translate(&shadow.offset);
let prim_index = self.create_primitive(
clip_and_scroll,
&info,
@@ -700,8 +687,6 @@ impl FrameBuilder {
self.shadow_prim_stack[idx].1.push((prim_index, clip_and_scroll));
}

let mut info = info.clone();
info.rect = new_rect;
let prim_index = self.create_primitive(
clip_and_scroll,
&info,
@@ -714,7 +699,7 @@ impl FrameBuilder {
self.add_primitive_to_hit_testing_list(&info, clip_and_scroll);
self.add_primitive_to_draw_list(prim_index, clip_and_scroll);
} else {
self.pending_shadow_contents.push((prim_index, clip_and_scroll, info));
self.pending_shadow_contents.push((prim_index, clip_and_scroll, *info));
}
}

@@ -727,7 +712,7 @@ impl FrameBuilder {

// Only run real blurs here (fast path zero blurs are handled above).
if blur_radius > 0.0 {
let shadow_rect = new_rect.inflate(
let shadow_rect = info.rect.inflate(
blur_radius,
blur_radius,
);
@@ -197,6 +197,7 @@ impl ToGpuBlocks for BrushPrimitive {
#[repr(C)]
pub struct LinePrimitive {
pub color: ColorF,
pub wavy_line_thickness: f32,
pub style: LineStyle,
pub orientation: LineOrientation,
}
@@ -205,10 +206,10 @@ impl ToGpuBlocks for LinePrimitive {
fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
request.push(self.color);
request.push([
self.wavy_line_thickness,
pack_as_float(self.style as u32),
pack_as_float(self.orientation as u32),
0.0,
0.0,
]);
}
}
@@ -148,11 +148,8 @@ pub struct RectangleDisplayItem {

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct LineDisplayItem {
pub baseline: f32, // LayerPixel
pub start: f32,
pub end: f32,
pub orientation: LineOrientation, // toggles whether above values are interpreted as x/y values
pub width: f32,
pub wavy_line_thickness: f32,
pub color: ColorF,
pub style: LineStyle,
}
@@ -773,21 +773,15 @@ impl DisplayListBuilder {
pub fn push_line(
&mut self,
info: &LayoutPrimitiveInfo,
baseline: f32,
start: f32,
end: f32,
wavy_line_thickness: f32,
orientation: LineOrientation,
width: f32,
color: ColorF,
color: &ColorF,
style: LineStyle,
) {
let item = SpecificDisplayItem::Line(LineDisplayItem {
baseline,
start,
end,
wavy_line_thickness,
orientation,
width,
color,
color: *color,
style,
});

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.