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

Full rectangular pixel snapping #1292

Merged
merged 3 commits into from May 26, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -84,23 +84,16 @@ vec2 clamp_rect(vec2 point, RectWithEndpoint rect) {
return clamp(point, rect.p0, rect.p1);
}

// Clamp 2 points at once.
vec4 clamp_rect(vec4 points, RectWithSize rect) {
return clamp(points, rect.p0.xyxy, rect.p0.xyxy + rect.size.xyxy);
}

vec4 clamp_rect(vec4 points, RectWithEndpoint rect) {
return clamp(points, rect.p0.xyxy, rect.p1.xyxy);
RectWithEndpoint intersect_rect(RectWithEndpoint a, RectWithEndpoint b) {
vec2 p0 = clamp_rect(a.p0, b);
vec2 p1 = clamp_rect(a.p1, b);
return RectWithEndpoint(p0, max(p0, p1));
}

RectWithSize intersect_rect(RectWithSize a, RectWithSize b) {
vec4 p = clamp_rect(vec4(a.p0, a.p0 + a.size), b);
return RectWithSize(p.xy, max(vec2(0.0), p.zw - p.xy));
}

RectWithEndpoint intersect_rect(RectWithEndpoint a, RectWithEndpoint b) {
vec4 p = clamp_rect(vec4(a.p0, a.p1), b);
return RectWithEndpoint(p.xy, max(p.xy, p.zw));
RectWithEndpoint r = intersect_rect(to_rect_with_endpoint(a),
to_rect_with_endpoint(b));
return to_rect_with_size(r);
}

float distance_to_line(vec2 p0, vec2 perp_dir, vec2 p) {
@@ -563,6 +556,30 @@ vec4 get_layer_pos(vec2 pos, Layer layer) {
return untransform(pos, n, a, layer.inv_transform);
}

// Compute a snapping offset in world space (adjusted to pixel ratio),
// given local position on the layer and a snap rectangle.
vec2 compute_snap_offset(vec2 local_pos,
RectWithSize local_clip_rect,
Layer layer,
RectWithSize raw_snap_rect) {
// Clamp the snap rectangle.
RectWithSize snap_rect = intersect_rect(intersect_rect(raw_snap_rect, local_clip_rect),
layer.local_clip_rect);
// Transform the snap corners to the world space.
vec4 world_snap_p0 = layer.transform * vec4(snap_rect.p0, 0.0, 1.0);
vec4 world_snap_p1 = layer.transform * vec4(snap_rect.p0 + snap_rect.size, 0.0, 1.0);
// Snap bounds in world coordinates, adjusted for pixel ratio. XY = top left, ZW = bottom right
vec4 world_snap = uDevicePixelRatio * vec4(world_snap_p0.xy, world_snap_p1.xy) /
vec4(world_snap_p0.ww, world_snap_p1.ww);
/// World offsets applied to the corners of the snap rectangle.
vec4 snap_offsets = floor(world_snap + 0.5) - world_snap;

/// Compute the position of this vertex inside the snap rectangle.
vec2 normalized_snap_pos = (local_pos - snap_rect.p0) / snap_rect.size;
/// Compute the actual world offset for this vertex needed to make it snap.
return mix(snap_offsets.xy, snap_offsets.zw, normalized_snap_pos);
}

struct VertexInfo {
vec2 local_pos;
vec2 screen_pos;
@@ -573,38 +590,32 @@ VertexInfo write_vertex(RectWithSize instance_rect,
float z,
Layer layer,
AlphaBatchTask task,
vec2 snap_ref) {
RectWithSize snap_rect) {

// Select the corner of the local rect that we are processing.
vec2 local_pos = instance_rect.p0 + instance_rect.size * aPosition.xy;

// xy = top left corner of the local rect, zw = position of current vertex.
vec4 local_p0_pos = vec4(snap_ref, local_pos);

// Clamp to the two local clip rects.
local_p0_pos = clamp_rect(local_p0_pos, local_clip_rect);
local_p0_pos = clamp_rect(local_p0_pos, layer.local_clip_rect);
vec2 clamped_local_pos = clamp_rect(clamp_rect(local_pos, local_clip_rect),
layer.local_clip_rect);

// Transform the top corner and current vertex to world space.
vec4 world_p0 = layer.transform * vec4(local_p0_pos.xy, 0.0, 1.0);
world_p0.xyz /= world_p0.w;
vec4 world_pos = layer.transform * vec4(local_p0_pos.zw, 0.0, 1.0);
world_pos.xyz /= world_pos.w;
/// Compute the snapping offset.
vec2 snap_offset = compute_snap_offset(clamped_local_pos, local_clip_rect, layer, snap_rect);

// Convert the world positions to device pixel space. xy=top left corner. zw=current vertex.
vec4 device_p0_pos = vec4(world_p0.xy, world_pos.xy) * uDevicePixelRatio;
// Transform the current vertex to the world cpace.
vec4 world_pos = layer.transform * vec4(clamped_local_pos, 0.0, 1.0);

// Calculate the distance to snap the vertex by (snap top left corner).
vec2 snap_delta = device_p0_pos.xy - floor(device_p0_pos.xy + 0.5);
// Convert the world positions to device pixel space.
vec2 device_pos = world_pos.xy / world_pos.w * uDevicePixelRatio;

// Apply offsets for the render task to get correct screen location.
vec2 final_pos = device_p0_pos.zw -
snap_delta -
vec2 final_pos = device_pos + snap_offset -
task.screen_space_origin +
task.render_target_origin;

gl_Position = uTransform * vec4(final_pos, z, 1.0);

VertexInfo vi = VertexInfo(local_p0_pos.zw, device_p0_pos.zw);
VertexInfo vi = VertexInfo(clamped_local_pos, device_pos);
return vi;
}

@@ -639,7 +650,7 @@ TransformVertexInfo write_transform_vertex(RectWithSize instance_rect,
float z,
Layer layer,
AlphaBatchTask task,
vec2 snap_ref) {
RectWithSize snap_rect) {
RectWithEndpoint local_rect = to_rect_with_endpoint(instance_rect);

vec2 current_local_pos, prev_local_pos, next_local_pos;
@@ -698,23 +709,21 @@ TransformVertexInfo write_transform_vertex(RectWithSize instance_rect,
adjusted_next_p0,
adjusted_next_p1);

// Calculate the snap amount based on the first vertex as a reference point.
vec4 world_p0 = layer.transform * vec4(snap_ref, 0.0, 1.0);
vec2 device_p0 = uDevicePixelRatio * world_p0.xy / world_p0.w;
vec2 snap_delta = device_p0 - floor(device_p0 + 0.5);
vec4 layer_pos = get_layer_pos(device_pos / uDevicePixelRatio, layer);

/// Compute the snapping offset.
vec2 snap_offset = compute_snap_offset(layer_pos.xy / layer_pos.w,
local_clip_rect, layer, snap_rect);

// Apply offsets for the render task to get correct screen location.
vec2 final_pos = device_pos -
snap_delta -
vec2 final_pos = device_pos + snap_offset -
task.screen_space_origin +
task.render_target_origin;

gl_Position = uTransform * vec4(final_pos, z, 1.0);

vLocalBounds = vec4(local_rect.p0, local_rect.p1);

vec4 layer_pos = get_layer_pos(device_pos / uDevicePixelRatio, layer);

return TransformVertexInfo(layer_pos.xyw, device_pos);
}

@@ -12,7 +12,7 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);

vPos = vi.local_pos - prim.local_rect.p0;

@@ -271,14 +271,14 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);
#else
VertexInfo vi = write_vertex(segment_rect,
prim.local_clip_rect,
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);
#endif

vLocalPos = vi.local_pos;
@@ -184,14 +184,14 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);
#else
VertexInfo vi = write_vertex(segment_rect,
prim.local_clip_rect,
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);
#endif

vLocalPos = vi.local_pos;
@@ -13,7 +13,7 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);

RenderTaskData child_task = fetch_render_task(prim.user_data1);
vUv.z = child_task.data1.x;
@@ -14,7 +14,7 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);

RenderTaskData child_task = fetch_render_task(prim.user_data1);
vUv.z = child_task.data1.x;
@@ -62,7 +62,7 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);
vLocalPos = vi.local_pos;
vec2 f = (vi.local_pos.xy - prim.local_rect.p0) / prim.local_rect.size;
#else
@@ -71,7 +71,7 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);

vec2 f = (vi.local_pos - segment_rect.p0) / segment_rect.size;
vPos = vi.local_pos;
@@ -14,15 +14,15 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);
vLocalPos = vi.local_pos;
#else
VertexInfo vi = write_vertex(prim.local_rect,
prim.local_clip_rect,
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);
vLocalPos = vi.local_pos - prim.local_rect.p0;
#endif

@@ -12,7 +12,7 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);

vPos = vi.local_pos - prim.local_rect.p0;

@@ -13,15 +13,15 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);
vLocalPos = vi.local_pos;
#else
VertexInfo vi = write_vertex(prim.local_rect,
prim.local_clip_rect,
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);
#endif

#ifdef WR_FEATURE_CLIP
@@ -18,7 +18,7 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
local_rect.p0);
local_rect);
vLocalPos = vi.local_pos;
vec2 f = (vi.local_pos.xy / vi.local_pos.z - local_rect.p0) / local_rect.size;
#else
@@ -27,7 +27,7 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
local_rect.p0);
local_rect);
vec2 f = (vi.local_pos - local_rect.p0) / local_rect.size;
#endif

@@ -11,15 +11,15 @@ void main(void) {
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);
vLocalPos = vi.local_pos;
#else
VertexInfo vi = write_vertex(prim.local_rect,
prim.local_clip_rect,
prim.z,
prim.layer,
prim.task,
prim.local_rect.p0);
prim.local_rect);
vLocalPos = vi.local_pos - prim.local_rect.p0;
#endif

Binary file not shown.
@@ -1,11 +1,12 @@
include aa/reftest.list
include blend/reftest.list
include mask/reftest.list
include scrolling/reftest.list
include filters/reftest.list
include boxshadow/reftest.list
include image/reftest.list
include border/reftest.list
include boxshadow/reftest.list
include filters/reftest.list
include gradient/reftest.list
include text/reftest.list
include image/reftest.list
include mask/reftest.list
include scrolling/reftest.list
include snap/reftest.list
include split/reftest.list
include aa/reftest.list
include text/reftest.list
@@ -0,0 +1,2 @@
== snap.yaml snap.png
== transform.yaml transform.png
Binary file not shown.
@@ -0,0 +1,15 @@
---
root:
items:
- type: rect
bounds: [ 1, 1, 5, 5 ]
color: green
- type: rect
bounds: [ 10.4, 1.8, 5, 5 ]
color: green
- type: rect
bounds: [ 21.5, 1.5, 5, 5 ]
color: green
- type: rect
bounds: [ 31.2, 1.6, 4.3, 5.5 ]
color: green
Binary file not shown.
@@ -0,0 +1,19 @@
---
root:
items:
# 45 degrees result in middle -+ 14.142, rounded to 14
- type: stacking-context
bounds: [0, 0, 60, 60]
transform: rotate-y(45)
items:
- type: rect
bounds: [ 10, 10, 40, 40 ]
color: blue
# 50 degrees result in middle -+ 12.856, rounded to 13
- type: stacking-context
bounds: [50, 0, 60, 60]
transform: rotate-x(50)
items:
- type: rect
bounds: [ 10, 10, 40, 40 ]
color: blue
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.