зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1465058 - Update webrender to commit 8e697f8cb1f1aab2e5f6b9b903eb7191340b10c5. r=Gankro
MozReview-Commit-ID: BakJj8upl1A --HG-- extra : rebase_source : 977723b4c807e1ac4887c957ff72a2628b2367c1
This commit is contained in:
Родитель
4dae1c8fc0
Коммит
0ffc26692e
|
@ -35,9 +35,7 @@ impl Example for App {
|
|||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
|
|
@ -47,13 +47,20 @@ impl Example for App {
|
|||
FilterOp::Opacity(PropertyBinding::Binding(self.opacity_key, self.opacity), self.opacity),
|
||||
];
|
||||
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
let reference_frame_id = builder.push_reference_frame(
|
||||
&info,
|
||||
Some(PropertyBinding::Binding(self.property_key, LayoutTransform::identity())),
|
||||
None,
|
||||
);
|
||||
|
||||
builder.push_clip_id(reference_frame_id);
|
||||
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
Some(PropertyBinding::Binding(self.property_key, LayoutTransform::identity())),
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
filters,
|
||||
GlyphRasterSpace::Screen,
|
||||
|
@ -73,6 +80,9 @@ impl Example for App {
|
|||
builder.pop_clip_id();
|
||||
|
||||
builder.pop_stacking_context();
|
||||
|
||||
builder.pop_clip_id();
|
||||
builder.pop_reference_frame();
|
||||
}
|
||||
|
||||
fn on_event(&mut self, win_event: winit::WindowEvent, api: &RenderApi, document_id: DocumentId) -> bool {
|
||||
|
|
|
@ -193,9 +193,7 @@ impl Example for App {
|
|||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
|
|
@ -251,9 +251,7 @@ impl Example for App {
|
|||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
None,
|
||||
api::TransformStyle::Flat,
|
||||
None,
|
||||
api::MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
api::GlyphRasterSpace::Screen,
|
||||
|
|
|
@ -69,7 +69,7 @@ impl App {
|
|||
|
||||
let document_id = api.add_document(size, layer);
|
||||
let mut txn = Transaction::new();
|
||||
txn.set_window_parameters(framebuffer_size, bounds, 1.0);
|
||||
txn.set_window_parameters(framebuffer_size, bounds, device_pixel_ratio);
|
||||
txn.set_root_pipeline(pipeline_id);
|
||||
api.send_transaction(document_id, txn);
|
||||
|
||||
|
@ -114,9 +114,7 @@ impl Example for App {
|
|||
builder.push_stacking_context(
|
||||
&LayoutPrimitiveInfo::new(doc.content_rect),
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
|
|
@ -102,9 +102,7 @@ impl App {
|
|||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
@ -148,9 +146,7 @@ impl Example for App {
|
|||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
|
|
@ -40,9 +40,7 @@ impl Example for App {
|
|||
sub_builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
@ -62,13 +60,20 @@ impl Example for App {
|
|||
);
|
||||
api.send_transaction(document_id, txn);
|
||||
|
||||
let info = LayoutPrimitiveInfo::new(sub_bounds);
|
||||
let reference_frame_id = builder.push_reference_frame(
|
||||
&info,
|
||||
Some(PropertyBinding::Binding(PropertyBindingKey::new(42), LayoutTransform::identity())),
|
||||
None,
|
||||
);
|
||||
builder.push_clip_id(reference_frame_id);
|
||||
|
||||
|
||||
// And this is for the root pipeline
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
Some(PropertyBinding::Binding(PropertyBindingKey::new(42), LayoutTransform::identity())),
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
@ -77,6 +82,9 @@ impl Example for App {
|
|||
builder.push_rect(&info, ColorF::new(1.0, 0.0, 0.0, 1.0));
|
||||
builder.push_iframe(&info, sub_pipeline_id, false);
|
||||
builder.pop_stacking_context();
|
||||
|
||||
builder.pop_clip_id();
|
||||
builder.pop_reference_frame();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,9 +42,7 @@ impl Example for App {
|
|||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
|
|
@ -180,9 +180,7 @@ impl Window {
|
|||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
|
|
@ -35,9 +35,7 @@ impl Example for App {
|
|||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
@ -50,9 +48,7 @@ impl Example for App {
|
|||
builder.push_stacking_context(
|
||||
&LayoutPrimitiveInfo::new((10, 10).by(0, 0)),
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
|
|
@ -94,9 +94,7 @@ impl Example for App {
|
|||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
|
|
@ -89,9 +89,7 @@ impl Example for App {
|
|||
builder.push_stacking_context(
|
||||
&info,
|
||||
None,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
MixBlendMode::Normal,
|
||||
Vec::new(),
|
||||
GlyphRasterSpace::Screen,
|
||||
|
|
|
@ -98,13 +98,3 @@ ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect,
|
|||
}
|
||||
|
||||
#endif //WR_VERTEX_SHADER
|
||||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
|
||||
//Note: identical to prim_shared
|
||||
float distance_to_line(vec2 p0, vec2 perp_dir, vec2 p) {
|
||||
vec2 dir_to_p0 = p0 - p;
|
||||
return dot(normalize(perp_dir), dir_to_p0);
|
||||
}
|
||||
|
||||
#endif //WR_FRAGMENT_SHADER
|
||||
|
|
|
@ -2,20 +2,58 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include shared,prim_shared,ellipse,shared_border
|
||||
#include shared,ellipse
|
||||
|
||||
flat varying vec4 vColor0;
|
||||
flat varying vec4 vColor1;
|
||||
// For edges, the colors are the same. For corners, these
|
||||
// are the colors of each edge making up the corner.
|
||||
flat varying vec4 vColor0[2];
|
||||
flat varying vec4 vColor1[2];
|
||||
|
||||
// A point + tangent defining the line where the edge
|
||||
// transition occurs. Used for corners only.
|
||||
flat varying vec4 vColorLine;
|
||||
flat varying int vFeatures;
|
||||
flat varying vec2 vClipCenter;
|
||||
flat varying vec4 vClipRadii;
|
||||
flat varying vec2 vClipSign;
|
||||
|
||||
// x = segment, y = styles, z = edge axes
|
||||
flat varying ivec3 vConfig;
|
||||
|
||||
// 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 vec4 vClipCenter_Sign;
|
||||
|
||||
// An outer and inner elliptical radii for border
|
||||
// corner clipping.
|
||||
flat varying vec4 vClipRadii;
|
||||
|
||||
// Reference point for determine edge clip lines.
|
||||
flat varying vec4 vEdgeReference;
|
||||
|
||||
// Stores widths/2 and widths/3 to save doing this in FS.
|
||||
flat varying vec4 vPartialWidths;
|
||||
|
||||
// Local space position
|
||||
varying vec2 vPos;
|
||||
|
||||
#define CLIP_RADII 1
|
||||
#define MIX_COLOR 2
|
||||
#define SEGMENT_TOP_LEFT 0
|
||||
#define SEGMENT_TOP_RIGHT 1
|
||||
#define SEGMENT_BOTTOM_RIGHT 2
|
||||
#define SEGMENT_BOTTOM_LEFT 3
|
||||
#define SEGMENT_LEFT 4
|
||||
#define SEGMENT_TOP 5
|
||||
#define SEGMENT_RIGHT 6
|
||||
#define SEGMENT_BOTTOM 7
|
||||
|
||||
// Border styles as defined in webrender_api/types.rs
|
||||
#define BORDER_STYLE_NONE 0
|
||||
#define BORDER_STYLE_SOLID 1
|
||||
#define BORDER_STYLE_DOUBLE 2
|
||||
#define BORDER_STYLE_DOTTED 3
|
||||
#define BORDER_STYLE_DASHED 4
|
||||
#define BORDER_STYLE_HIDDEN 5
|
||||
#define BORDER_STYLE_GROOVE 6
|
||||
#define BORDER_STYLE_RIDGE 7
|
||||
#define BORDER_STYLE_INSET 8
|
||||
#define BORDER_STYLE_OUTSET 9
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
|
@ -27,15 +65,6 @@ in int aFlags;
|
|||
in vec2 aWidths;
|
||||
in vec2 aRadii;
|
||||
|
||||
#define SEGMENT_TOP_LEFT 0
|
||||
#define SEGMENT_TOP_RIGHT 1
|
||||
#define SEGMENT_BOTTOM_RIGHT 2
|
||||
#define SEGMENT_BOTTOM_LEFT 3
|
||||
#define SEGMENT_LEFT 4
|
||||
#define SEGMENT_TOP 5
|
||||
#define SEGMENT_RIGHT 6
|
||||
#define SEGMENT_BOTTOM 7
|
||||
|
||||
vec2 get_outer_corner_scale(int segment) {
|
||||
vec2 p;
|
||||
|
||||
|
@ -61,67 +90,252 @@ vec2 get_outer_corner_scale(int segment) {
|
|||
return p;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
vec2 pos = aRect.xy + aRect.zw * aPosition.xy;
|
||||
vec4 mod_color(vec4 color, float f) {
|
||||
return vec4(clamp(color.rgb * f, vec3(0.0), vec3(color.a)), color.a);
|
||||
}
|
||||
|
||||
int segment = aFlags & 0xff;
|
||||
int style = (aFlags >> 8) & 0xff;
|
||||
vec4[2] get_colors_for_side(vec4 color, int style) {
|
||||
vec4 result[2];
|
||||
const vec2 f = vec2(1.3, 0.7);
|
||||
|
||||
vec2 outer_scale = get_outer_corner_scale(segment);
|
||||
vec2 outer = aRect.xy + outer_scale * aRect.zw;
|
||||
vec2 clip_sign = 1.0 - 2.0 * outer_scale;
|
||||
|
||||
vColor0 = aColor0;
|
||||
vColor1 = aColor1;
|
||||
vPos = pos;
|
||||
|
||||
vFeatures = 0;
|
||||
vClipSign = clip_sign;
|
||||
vClipCenter = outer + clip_sign * aRadii;
|
||||
vClipRadii = vec4(aRadii, aRadii - aWidths);
|
||||
vColorLine = vec4(0.0);
|
||||
|
||||
switch (segment) {
|
||||
case SEGMENT_TOP_LEFT:
|
||||
case SEGMENT_TOP_RIGHT:
|
||||
case SEGMENT_BOTTOM_RIGHT:
|
||||
case SEGMENT_BOTTOM_LEFT:
|
||||
vFeatures |= (CLIP_RADII | MIX_COLOR);
|
||||
vColorLine = vec4(outer, aWidths.y * -clip_sign.y, aWidths.x * clip_sign.x);
|
||||
switch (style) {
|
||||
case BORDER_STYLE_GROOVE:
|
||||
result[0] = mod_color(color, f.x);
|
||||
result[1] = mod_color(color, f.y);
|
||||
break;
|
||||
case BORDER_STYLE_RIDGE:
|
||||
result[0] = mod_color(color, f.y);
|
||||
result[1] = mod_color(color, f.x);
|
||||
break;
|
||||
default:
|
||||
result[0] = color;
|
||||
result[1] = color;
|
||||
break;
|
||||
}
|
||||
|
||||
gl_Position = uTransform * vec4(aTaskOrigin + pos, 0.0, 1.0);
|
||||
return result;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
int segment = aFlags & 0xff;
|
||||
int style0 = (aFlags >> 8) & 0xff;
|
||||
int style1 = (aFlags >> 16) & 0xff;
|
||||
|
||||
vec2 outer_scale = get_outer_corner_scale(segment);
|
||||
vec2 outer = outer_scale * aRect.zw;
|
||||
vec2 clip_sign = 1.0 - 2.0 * outer_scale;
|
||||
|
||||
// Set some flags used by the FS to determine the
|
||||
// orientation of the two edges in this corner.
|
||||
ivec2 edge_axis;
|
||||
// Derive the positions for the edge clips, which must be handled
|
||||
// differently between corners and edges.
|
||||
vec2 edge_reference;
|
||||
switch (segment) {
|
||||
case SEGMENT_TOP_LEFT:
|
||||
edge_axis = ivec2(0, 1);
|
||||
edge_reference = outer;
|
||||
break;
|
||||
case SEGMENT_TOP_RIGHT:
|
||||
edge_axis = ivec2(1, 0);
|
||||
edge_reference = vec2(outer.x - aWidths.x, outer.y);
|
||||
break;
|
||||
case SEGMENT_BOTTOM_RIGHT:
|
||||
edge_axis = ivec2(0, 1);
|
||||
edge_reference = outer - aWidths;
|
||||
break;
|
||||
case SEGMENT_BOTTOM_LEFT:
|
||||
edge_axis = ivec2(1, 0);
|
||||
edge_reference = vec2(outer.x, outer.y - aWidths.y);
|
||||
break;
|
||||
case SEGMENT_TOP:
|
||||
case SEGMENT_BOTTOM:
|
||||
edge_axis = ivec2(1, 1);
|
||||
edge_reference = vec2(0.0);
|
||||
break;
|
||||
case SEGMENT_LEFT:
|
||||
case SEGMENT_RIGHT:
|
||||
default:
|
||||
edge_axis = ivec2(0, 0);
|
||||
edge_reference = vec2(0.0);
|
||||
break;
|
||||
}
|
||||
|
||||
vConfig = ivec3(
|
||||
segment,
|
||||
style0 | (style1 << 16),
|
||||
edge_axis.x | (edge_axis.y << 16)
|
||||
);
|
||||
vPartialWidths = vec4(aWidths / 3.0, aWidths / 2.0);
|
||||
vPos = aRect.zw * aPosition.xy;
|
||||
|
||||
vColor0 = get_colors_for_side(aColor0, style0);
|
||||
vColor1 = get_colors_for_side(aColor1, style1);
|
||||
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);
|
||||
vEdgeReference = vec4(edge_reference, edge_reference + aWidths);
|
||||
|
||||
gl_Position = uTransform * vec4(aTaskOrigin + aRect.xy + vPos, 0.0, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
vec4 evaluate_color_for_style_in_corner(
|
||||
vec2 clip_relative_pos,
|
||||
int style,
|
||||
vec4 color[2],
|
||||
vec4 clip_radii,
|
||||
float mix_factor,
|
||||
int segment,
|
||||
float aa_range
|
||||
) {
|
||||
switch (style) {
|
||||
case BORDER_STYLE_DOUBLE: {
|
||||
// Get the distances from 0.33 of the radii, and
|
||||
// also 0.67 of the radii. Use these to form a
|
||||
// SDF subtraction which will clip out the inside
|
||||
// third of the rounded edge.
|
||||
float d_radii_a = distance_to_ellipse(
|
||||
clip_relative_pos,
|
||||
clip_radii.xy - vPartialWidths.xy,
|
||||
aa_range
|
||||
);
|
||||
float d_radii_b = distance_to_ellipse(
|
||||
clip_relative_pos,
|
||||
clip_radii.xy - 2.0 * vPartialWidths.xy,
|
||||
aa_range
|
||||
);
|
||||
float d = min(-d_radii_a, d_radii_b);
|
||||
float alpha = distance_aa(aa_range, d);
|
||||
return alpha * color[0];
|
||||
}
|
||||
case BORDER_STYLE_GROOVE:
|
||||
case BORDER_STYLE_RIDGE: {
|
||||
float d = distance_to_ellipse(
|
||||
clip_relative_pos,
|
||||
clip_radii.xy - vPartialWidths.zw,
|
||||
aa_range
|
||||
);
|
||||
float alpha = distance_aa(aa_range, d);
|
||||
float swizzled_factor;
|
||||
switch (segment) {
|
||||
case SEGMENT_TOP_LEFT: swizzled_factor = 0.0; break;
|
||||
case SEGMENT_TOP_RIGHT: swizzled_factor = mix_factor; break;
|
||||
case SEGMENT_BOTTOM_RIGHT: swizzled_factor = 1.0; break;
|
||||
case SEGMENT_BOTTOM_LEFT: swizzled_factor = 1.0 - mix_factor; break;
|
||||
default: swizzled_factor = 0.0; break;
|
||||
};
|
||||
vec4 c0 = mix(color[1], color[0], swizzled_factor);
|
||||
vec4 c1 = mix(color[0], color[1], swizzled_factor);
|
||||
return mix(c0, c1, alpha);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return color[0];
|
||||
}
|
||||
|
||||
vec4 evaluate_color_for_style_in_edge(
|
||||
vec2 pos,
|
||||
int style,
|
||||
vec4 color[2],
|
||||
float aa_range,
|
||||
int edge_axis
|
||||
) {
|
||||
switch (style) {
|
||||
case BORDER_STYLE_DOUBLE: {
|
||||
float d0 = -1.0;
|
||||
float d1 = -1.0;
|
||||
if (vPartialWidths[edge_axis] > 1.0) {
|
||||
vec2 ref = vec2(
|
||||
vEdgeReference[edge_axis] + vPartialWidths[edge_axis],
|
||||
vEdgeReference[edge_axis+2] - vPartialWidths[edge_axis]
|
||||
);
|
||||
d0 = pos[edge_axis] - ref.x;
|
||||
d1 = ref.y - pos[edge_axis];
|
||||
}
|
||||
float d = min(d0, d1);
|
||||
float alpha = distance_aa(aa_range, d);
|
||||
return alpha * color[0];
|
||||
}
|
||||
case BORDER_STYLE_GROOVE:
|
||||
case BORDER_STYLE_RIDGE: {
|
||||
float ref = vEdgeReference[edge_axis] + vPartialWidths[edge_axis+2];
|
||||
float d = pos[edge_axis] - ref;
|
||||
float alpha = distance_aa(aa_range, d);
|
||||
return mix(color[0], color[1], alpha);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return color[0];
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
float aa_range = compute_aa_range(vPos);
|
||||
float d = -1.0;
|
||||
vec4 color0, color1;
|
||||
|
||||
int segment = vConfig.x;
|
||||
ivec2 style = ivec2(vConfig.y & 0xffff, vConfig.y >> 16);
|
||||
ivec2 edge_axis = ivec2(vConfig.z & 0xffff, vConfig.z >> 16);
|
||||
|
||||
// Apply color mix
|
||||
float mix_factor = 0.0;
|
||||
if ((vFeatures & MIX_COLOR) != 0) {
|
||||
if (edge_axis.x != edge_axis.y) {
|
||||
float d_line = distance_to_line(vColorLine.xy, vColorLine.zw, vPos);
|
||||
mix_factor = distance_aa(aa_range, -d_line);
|
||||
}
|
||||
|
||||
// Apply clip radii
|
||||
if ((vFeatures & CLIP_RADII) != 0) {
|
||||
vec2 p = vPos - vClipCenter;
|
||||
if (vClipSign.x * p.x < 0.0 && vClipSign.y * p.y < 0.0) {
|
||||
float d_radii_a = distance_to_ellipse(p, vClipRadii.xy, aa_range);
|
||||
float d_radii_b = distance_to_ellipse(p, vClipRadii.zw, aa_range);
|
||||
// Check if inside 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)));
|
||||
|
||||
if (in_clip_region) {
|
||||
float d_radii_a = distance_to_ellipse(clip_relative_pos, vClipRadii.xy, aa_range);
|
||||
float d_radii_b = distance_to_ellipse(clip_relative_pos, vClipRadii.zw, aa_range);
|
||||
float d_radii = max(d_radii_a, -d_radii_b);
|
||||
d = max(d, d_radii);
|
||||
}
|
||||
|
||||
color0 = evaluate_color_for_style_in_corner(
|
||||
clip_relative_pos,
|
||||
style.x,
|
||||
vColor0,
|
||||
vClipRadii,
|
||||
mix_factor,
|
||||
segment,
|
||||
aa_range
|
||||
);
|
||||
color1 = evaluate_color_for_style_in_corner(
|
||||
clip_relative_pos,
|
||||
style.y,
|
||||
vColor1,
|
||||
vClipRadii,
|
||||
mix_factor,
|
||||
segment,
|
||||
aa_range
|
||||
);
|
||||
} else {
|
||||
color0 = evaluate_color_for_style_in_edge(
|
||||
vPos,
|
||||
style.x,
|
||||
vColor0,
|
||||
aa_range,
|
||||
edge_axis.x
|
||||
);
|
||||
color1 = evaluate_color_for_style_in_edge(
|
||||
vPos,
|
||||
style.y,
|
||||
vColor1,
|
||||
aa_range,
|
||||
edge_axis.y
|
||||
);
|
||||
}
|
||||
|
||||
float alpha = distance_aa(aa_range, d);
|
||||
vec4 color = mix(vColor0, vColor1, mix_factor);
|
||||
vec4 color = mix(color0, color1, mix_factor);
|
||||
oFragColor = color * alpha;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,11 +25,6 @@ vec2 clamp_rect(vec2 pt, RectWithSize rect) {
|
|||
return clamp(pt, rect.p0, rect.p0 + rect.size);
|
||||
}
|
||||
|
||||
float distance_to_line(vec2 p0, vec2 perp_dir, vec2 p) {
|
||||
vec2 dir_to_p0 = p0 - p;
|
||||
return dot(normalize(perp_dir), dir_to_p0);
|
||||
}
|
||||
|
||||
// TODO: convert back to RectWithEndPoint if driver issues are resolved, if ever.
|
||||
flat varying vec4 vClipMaskUvBounds;
|
||||
varying vec3 vClipMaskUv;
|
||||
|
|
|
@ -56,6 +56,61 @@
|
|||
#else
|
||||
out vec4 oFragColor;
|
||||
#endif
|
||||
|
||||
#define EPSILON 0.0001
|
||||
|
||||
float distance_to_line(vec2 p0, vec2 perp_dir, vec2 p) {
|
||||
vec2 dir_to_p0 = p0 - p;
|
||||
return dot(normalize(perp_dir), dir_to_p0);
|
||||
}
|
||||
|
||||
/// Find the appropriate half range to apply the AA approximation over.
|
||||
/// This range represents a coefficient to go from one CSS pixel to half a device pixel.
|
||||
float compute_aa_range(vec2 position) {
|
||||
// The constant factor is chosen to compensate for the fact that length(fw) is equal
|
||||
// to sqrt(2) times the device pixel ratio in the typical case. 0.5/sqrt(2) = 0.35355.
|
||||
//
|
||||
// This coefficient is chosen to ensure that any sample 0.5 pixels or more inside of
|
||||
// the shape has no anti-aliasing applied to it (since pixels are sampled at their center,
|
||||
// such a pixel (axis aligned) is fully inside the border). We need this so that antialiased
|
||||
// curves properly connect with non-antialiased vertical or horizontal lines, among other things.
|
||||
//
|
||||
// Lines over a half-pixel away from the pixel center *can* intersect with the pixel square;
|
||||
// indeed, unless they are horizontal or vertical, they are guaranteed to. However, choosing
|
||||
// a nonzero area for such pixels causes noticeable artifacts at the junction between an anti-
|
||||
// aliased corner and a straight edge.
|
||||
//
|
||||
// We may want to adjust this constant in specific scenarios (for example keep the principled
|
||||
// value for straight edges where we want pixel-perfect equivalence with non antialiased lines
|
||||
// when axis aligned, while selecting a larger and smoother aa range on curves).
|
||||
return 0.35355 * length(fwidth(position));
|
||||
}
|
||||
|
||||
/// Return the blending coefficient for distance antialiasing.
|
||||
///
|
||||
/// 0.0 means inside the shape, 1.0 means outside.
|
||||
///
|
||||
/// This cubic polynomial approximates the area of a 1x1 pixel square under a
|
||||
/// line, given the signed Euclidean distance from the center of the square to
|
||||
/// that line. Calculating the *exact* area would require taking into account
|
||||
/// not only this distance but also the angle of the line. However, in
|
||||
/// practice, this complexity is not required, as the area is roughly the same
|
||||
/// regardless of the angle.
|
||||
///
|
||||
/// The coefficients of this polynomial were determined through least-squares
|
||||
/// regression and are accurate to within 2.16% of the total area of the pixel
|
||||
/// square 95% of the time, with a maximum error of 3.53%.
|
||||
///
|
||||
/// See the comments in `compute_aa_range()` for more information on the
|
||||
/// cutoff values of -0.5 and 0.5.
|
||||
float distance_aa(float aa_range, float signed_distance) {
|
||||
float dist = 0.5 * signed_distance / aa_range;
|
||||
if (dist <= -0.5 + EPSILON)
|
||||
return 1.0;
|
||||
if (dist >= 0.5 - EPSILON)
|
||||
return 0.0;
|
||||
return 0.5 + dist * (0.8431027 * dist * dist - 1.14453603);
|
||||
}
|
||||
#endif
|
||||
|
||||
//======================================================================================
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
// Border styles as defined in webrender_api/types.rs
|
||||
#define BORDER_STYLE_NONE 0
|
||||
#define BORDER_STYLE_SOLID 1
|
||||
|
@ -16,6 +14,8 @@
|
|||
#define BORDER_STYLE_INSET 8
|
||||
#define BORDER_STYLE_OUTSET 9
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
||||
struct Border {
|
||||
vec4 style;
|
||||
vec4 widths;
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#define EPSILON 0.0001
|
||||
|
||||
flat varying vec4 vTransformBounds;
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
|
@ -16,54 +14,6 @@ void init_transform_vs(vec4 local_bounds) {
|
|||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
|
||||
/// Find the appropriate half range to apply the AA approximation over.
|
||||
/// This range represents a coefficient to go from one CSS pixel to half a device pixel.
|
||||
float compute_aa_range(vec2 position) {
|
||||
// The constant factor is chosen to compensate for the fact that length(fw) is equal
|
||||
// to sqrt(2) times the device pixel ratio in the typical case. 0.5/sqrt(2) = 0.35355.
|
||||
//
|
||||
// This coefficient is chosen to ensure that any sample 0.5 pixels or more inside of
|
||||
// the shape has no anti-aliasing applied to it (since pixels are sampled at their center,
|
||||
// such a pixel (axis aligned) is fully inside the border). We need this so that antialiased
|
||||
// curves properly connect with non-antialiased vertical or horizontal lines, among other things.
|
||||
//
|
||||
// Lines over a half-pixel away from the pixel center *can* intersect with the pixel square;
|
||||
// indeed, unless they are horizontal or vertical, they are guaranteed to. However, choosing
|
||||
// a nonzero area for such pixels causes noticeable artifacts at the junction between an anti-
|
||||
// aliased corner and a straight edge.
|
||||
//
|
||||
// We may want to adjust this constant in specific scenarios (for example keep the principled
|
||||
// value for straight edges where we want pixel-perfect equivalence with non antialiased lines
|
||||
// when axis aligned, while selecting a larger and smoother aa range on curves).
|
||||
return 0.35355 * length(fwidth(position));
|
||||
}
|
||||
|
||||
/// Return the blending coefficient for distance antialiasing.
|
||||
///
|
||||
/// 0.0 means inside the shape, 1.0 means outside.
|
||||
///
|
||||
/// This cubic polynomial approximates the area of a 1x1 pixel square under a
|
||||
/// line, given the signed Euclidean distance from the center of the square to
|
||||
/// that line. Calculating the *exact* area would require taking into account
|
||||
/// not only this distance but also the angle of the line. However, in
|
||||
/// practice, this complexity is not required, as the area is roughly the same
|
||||
/// regardless of the angle.
|
||||
///
|
||||
/// The coefficients of this polynomial were determined through least-squares
|
||||
/// regression and are accurate to within 2.16% of the total area of the pixel
|
||||
/// square 95% of the time, with a maximum error of 3.53%.
|
||||
///
|
||||
/// See the comments in `compute_aa_range()` for more information on the
|
||||
/// cutoff values of -0.5 and 0.5.
|
||||
float distance_aa(float aa_range, float signed_distance) {
|
||||
float dist = 0.5 * signed_distance / aa_range;
|
||||
if (dist <= -0.5 + EPSILON)
|
||||
return 1.0;
|
||||
if (dist >= 0.5 - EPSILON)
|
||||
return 0.0;
|
||||
return 0.5 + dist * (0.8431027 * dist * dist - 1.14453603);
|
||||
}
|
||||
|
||||
float signed_distance_rect(vec2 pos, vec2 p0, vec2 p1) {
|
||||
vec2 d = max(p0 - pos, pos - p1);
|
||||
return length(max(vec2(0.0), d)) + min(0.0, max(d.x, d.y));
|
||||
|
|
|
@ -471,16 +471,16 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
BorderStyle::Solid |
|
||||
BorderStyle::Hidden |
|
||||
BorderStyle::None |
|
||||
BorderStyle::Double |
|
||||
BorderStyle::Inset |
|
||||
BorderStyle::Groove |
|
||||
BorderStyle::Ridge |
|
||||
BorderStyle::Outset => {
|
||||
true
|
||||
}
|
||||
|
||||
BorderStyle::Double |
|
||||
BorderStyle::Dotted |
|
||||
BorderStyle::Dashed |
|
||||
BorderStyle::Groove |
|
||||
BorderStyle::Ridge => {
|
||||
BorderStyle::Dashed => {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -1015,10 +1015,17 @@ impl DotInfo {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BorderSegmentInfo {
|
||||
task_rect: DeviceRect,
|
||||
segment: BorderSegment,
|
||||
radius: DeviceSize,
|
||||
widths: DeviceSize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BorderRenderTaskInfo {
|
||||
pub instances: Vec<BorderInstance>,
|
||||
pub segments: Vec<BrushSegment>,
|
||||
pub border_segments: Vec<BorderSegmentInfo>,
|
||||
pub size: DeviceIntSize,
|
||||
}
|
||||
|
||||
|
@ -1028,9 +1035,9 @@ impl BorderRenderTaskInfo {
|
|||
border: &NormalBorder,
|
||||
widths: &BorderWidths,
|
||||
scale: LayoutToDeviceScale,
|
||||
brush_segments: &mut Vec<BrushSegment>,
|
||||
) -> Self {
|
||||
let mut instances = Vec::new();
|
||||
let mut segments = Vec::new();
|
||||
let mut border_segments = Vec::new();
|
||||
|
||||
let dp_width_top = (widths.top * scale.0).ceil();
|
||||
let dp_width_bottom = (widths.bottom * scale.0).ceil();
|
||||
|
@ -1088,15 +1095,6 @@ impl BorderRenderTaskInfo {
|
|||
dp_size_tl.height.max(dp_size_tr.height) + height_inner + dp_size_bl.height.max(dp_size_br.height),
|
||||
);
|
||||
|
||||
// These modulate colors are not part of the specification. They
|
||||
// are derived from the Gecko source code and experimentation, and
|
||||
// used to modulate the colors in order to generate colors for
|
||||
// the inset/outset and groove/ridge border styles.
|
||||
let left_color = border.left.border_color(1.0, 2.0 / 3.0, 0.3, 0.7);
|
||||
let top_color = border.top.border_color(1.0, 2.0 / 3.0, 0.3, 0.7);
|
||||
let right_color = border.right.border_color(2.0 / 3.0, 1.0, 0.7, 0.3);
|
||||
let bottom_color = border.bottom.border_color(2.0 / 3.0, 1.0, 0.7, 0.3);
|
||||
|
||||
add_edge_segment(
|
||||
LayoutRect::from_floats(
|
||||
rect.origin.x,
|
||||
|
@ -1110,13 +1108,12 @@ impl BorderRenderTaskInfo {
|
|||
dp_width_left,
|
||||
size.height - dp_size_bl.height,
|
||||
),
|
||||
border.left.style,
|
||||
left_color,
|
||||
&border.left,
|
||||
BorderSegment::Left,
|
||||
EdgeAaSegmentMask::LEFT | EdgeAaSegmentMask::RIGHT,
|
||||
&mut instances,
|
||||
&mut border_segments,
|
||||
BrushFlags::SEGMENT_RELATIVE | BrushFlags::SEGMENT_REPEAT_Y,
|
||||
&mut segments,
|
||||
brush_segments,
|
||||
);
|
||||
|
||||
add_edge_segment(
|
||||
|
@ -1132,13 +1129,12 @@ impl BorderRenderTaskInfo {
|
|||
size.width - dp_size_tr.width,
|
||||
dp_width_top,
|
||||
),
|
||||
border.top.style,
|
||||
top_color,
|
||||
&border.top,
|
||||
BorderSegment::Top,
|
||||
EdgeAaSegmentMask::TOP | EdgeAaSegmentMask::BOTTOM,
|
||||
&mut instances,
|
||||
&mut border_segments,
|
||||
BrushFlags::SEGMENT_RELATIVE | BrushFlags::SEGMENT_REPEAT_X,
|
||||
&mut segments,
|
||||
brush_segments,
|
||||
);
|
||||
|
||||
add_edge_segment(
|
||||
|
@ -1154,13 +1150,12 @@ impl BorderRenderTaskInfo {
|
|||
size.width,
|
||||
size.height - dp_size_br.height,
|
||||
),
|
||||
border.right.style,
|
||||
right_color,
|
||||
&border.right,
|
||||
BorderSegment::Right,
|
||||
EdgeAaSegmentMask::RIGHT | EdgeAaSegmentMask::LEFT,
|
||||
&mut instances,
|
||||
&mut border_segments,
|
||||
BrushFlags::SEGMENT_RELATIVE | BrushFlags::SEGMENT_REPEAT_Y,
|
||||
&mut segments,
|
||||
brush_segments,
|
||||
);
|
||||
|
||||
add_edge_segment(
|
||||
|
@ -1176,13 +1171,12 @@ impl BorderRenderTaskInfo {
|
|||
size.width - dp_size_br.width,
|
||||
size.height,
|
||||
),
|
||||
border.bottom.style,
|
||||
bottom_color,
|
||||
&border.bottom,
|
||||
BorderSegment::Bottom,
|
||||
EdgeAaSegmentMask::BOTTOM | EdgeAaSegmentMask::TOP,
|
||||
&mut instances,
|
||||
&mut border_segments,
|
||||
BrushFlags::SEGMENT_RELATIVE | BrushFlags::SEGMENT_REPEAT_X,
|
||||
&mut segments,
|
||||
brush_segments,
|
||||
);
|
||||
|
||||
add_corner_segment(
|
||||
|
@ -1198,16 +1192,14 @@ impl BorderRenderTaskInfo {
|
|||
dp_size_tl.width,
|
||||
dp_size_tl.height,
|
||||
),
|
||||
border.left.style,
|
||||
left_color,
|
||||
border.top.style,
|
||||
top_color,
|
||||
&border.left,
|
||||
&border.top,
|
||||
DeviceSize::new(dp_width_left, dp_width_top),
|
||||
dp_corner_tl,
|
||||
BorderSegment::TopLeft,
|
||||
EdgeAaSegmentMask::TOP | EdgeAaSegmentMask::LEFT,
|
||||
&mut instances,
|
||||
&mut segments,
|
||||
&mut border_segments,
|
||||
brush_segments,
|
||||
);
|
||||
|
||||
add_corner_segment(
|
||||
|
@ -1223,16 +1215,14 @@ impl BorderRenderTaskInfo {
|
|||
size.width,
|
||||
dp_size_tr.height,
|
||||
),
|
||||
border.top.style,
|
||||
top_color,
|
||||
border.right.style,
|
||||
right_color,
|
||||
&border.top,
|
||||
&border.right,
|
||||
DeviceSize::new(dp_width_right, dp_width_top),
|
||||
dp_corner_tr,
|
||||
BorderSegment::TopRight,
|
||||
EdgeAaSegmentMask::TOP | EdgeAaSegmentMask::RIGHT,
|
||||
&mut instances,
|
||||
&mut segments,
|
||||
&mut border_segments,
|
||||
brush_segments,
|
||||
);
|
||||
|
||||
add_corner_segment(
|
||||
|
@ -1248,16 +1238,14 @@ impl BorderRenderTaskInfo {
|
|||
size.width,
|
||||
size.height,
|
||||
),
|
||||
border.right.style,
|
||||
right_color,
|
||||
border.bottom.style,
|
||||
bottom_color,
|
||||
&border.right,
|
||||
&border.bottom,
|
||||
DeviceSize::new(dp_width_right, dp_width_bottom),
|
||||
dp_corner_br,
|
||||
BorderSegment::BottomRight,
|
||||
EdgeAaSegmentMask::BOTTOM | EdgeAaSegmentMask::RIGHT,
|
||||
&mut instances,
|
||||
&mut segments,
|
||||
&mut border_segments,
|
||||
brush_segments,
|
||||
);
|
||||
|
||||
add_corner_segment(
|
||||
|
@ -1273,24 +1261,82 @@ impl BorderRenderTaskInfo {
|
|||
dp_size_bl.width,
|
||||
size.height,
|
||||
),
|
||||
border.bottom.style,
|
||||
bottom_color,
|
||||
border.left.style,
|
||||
left_color,
|
||||
&border.bottom,
|
||||
&border.left,
|
||||
DeviceSize::new(dp_width_left, dp_width_bottom),
|
||||
dp_corner_bl,
|
||||
BorderSegment::BottomLeft,
|
||||
EdgeAaSegmentMask::BOTTOM | EdgeAaSegmentMask::LEFT,
|
||||
&mut instances,
|
||||
&mut segments,
|
||||
&mut border_segments,
|
||||
brush_segments,
|
||||
);
|
||||
|
||||
BorderRenderTaskInfo {
|
||||
segments,
|
||||
instances,
|
||||
border_segments,
|
||||
size: size.to_i32(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_instances(
|
||||
&self,
|
||||
border: &NormalBorder,
|
||||
) -> Vec<BorderInstance> {
|
||||
let mut instances = Vec::new();
|
||||
|
||||
for info in &self.border_segments {
|
||||
let (side0, side1, flip0, flip1) = match info.segment {
|
||||
BorderSegment::Left => (&border.left, &border.left, false, false),
|
||||
BorderSegment::Top => (&border.top, &border.top, false, false),
|
||||
BorderSegment::Right => (&border.right, &border.right, true, true),
|
||||
BorderSegment::Bottom => (&border.bottom, &border.bottom, true, true),
|
||||
BorderSegment::TopLeft => (&border.left, &border.top, false, false),
|
||||
BorderSegment::TopRight => (&border.top, &border.right, false, true),
|
||||
BorderSegment::BottomRight => (&border.right, &border.bottom, true, true),
|
||||
BorderSegment::BottomLeft => (&border.bottom, &border.left, true, false),
|
||||
};
|
||||
|
||||
let style0 = if side0.style.is_hidden() {
|
||||
side1.style
|
||||
} else {
|
||||
side0.style
|
||||
};
|
||||
let style1 = if side1.style.is_hidden() {
|
||||
side0.style
|
||||
} else {
|
||||
side1.style
|
||||
};
|
||||
|
||||
// These modulate colors are not part of the specification. They
|
||||
// are derived from the Gecko source code and experimentation, and
|
||||
// used to modulate the colors in order to generate colors for
|
||||
// the inset/outset and groove/ridge border styles.
|
||||
let color0 = if flip0 {
|
||||
side0.border_color(2.0 / 3.0, 1.0, 0.7, 0.3)
|
||||
} else {
|
||||
side0.border_color(1.0, 2.0 / 3.0, 0.3, 0.7)
|
||||
};
|
||||
|
||||
let color1 = if flip1 {
|
||||
side1.border_color(2.0 / 3.0, 1.0, 0.7, 0.3)
|
||||
} else {
|
||||
side1.border_color(1.0, 2.0 / 3.0, 0.3, 0.7)
|
||||
};
|
||||
|
||||
add_segment(
|
||||
info.task_rect,
|
||||
style0,
|
||||
style1,
|
||||
color0,
|
||||
color1,
|
||||
info.segment,
|
||||
&mut instances,
|
||||
info.widths,
|
||||
info.radius,
|
||||
);
|
||||
}
|
||||
|
||||
instances
|
||||
}
|
||||
}
|
||||
|
||||
fn add_brush_segment(
|
||||
|
@ -1347,23 +1393,16 @@ fn add_segment(
|
|||
fn add_corner_segment(
|
||||
image_rect: LayoutRect,
|
||||
task_rect: DeviceRect,
|
||||
mut style0: BorderStyle,
|
||||
color0: ColorF,
|
||||
mut style1: BorderStyle,
|
||||
color1: ColorF,
|
||||
side0: &BorderSide,
|
||||
side1: &BorderSide,
|
||||
widths: DeviceSize,
|
||||
radius: DeviceSize,
|
||||
segment: BorderSegment,
|
||||
edge_flags: EdgeAaSegmentMask,
|
||||
instances: &mut Vec<BorderInstance>,
|
||||
border_segments: &mut Vec<BorderSegmentInfo>,
|
||||
brush_segments: &mut Vec<BrushSegment>,
|
||||
) {
|
||||
// TODO(gw): This will need to be a bit more involved when
|
||||
// we support other border types here. For example,
|
||||
// groove / ridge borders will always need to
|
||||
// use two instances.
|
||||
|
||||
if color0.a <= 0.0 && color1.a <= 0.0 {
|
||||
if side0.color.a <= 0.0 && side1.color.a <= 0.0 {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1371,31 +1410,16 @@ fn add_corner_segment(
|
|||
return;
|
||||
}
|
||||
|
||||
let style0_hidden = style0 == BorderStyle::Hidden || style0 == BorderStyle::None;
|
||||
let style1_hidden = style1 == BorderStyle::Hidden || style1 == BorderStyle::None;
|
||||
|
||||
if style0_hidden && style1_hidden {
|
||||
if side0.style.is_hidden() && side1.style.is_hidden() {
|
||||
return;
|
||||
}
|
||||
|
||||
if style0_hidden {
|
||||
style0 = style1;
|
||||
}
|
||||
if style1_hidden {
|
||||
style1 = style0;
|
||||
}
|
||||
|
||||
add_segment(
|
||||
border_segments.push(BorderSegmentInfo {
|
||||
task_rect,
|
||||
style0,
|
||||
style1,
|
||||
color0,
|
||||
color1,
|
||||
segment,
|
||||
instances,
|
||||
widths,
|
||||
radius,
|
||||
);
|
||||
widths,
|
||||
});
|
||||
|
||||
add_brush_segment(
|
||||
image_rect,
|
||||
|
@ -1409,33 +1433,27 @@ fn add_corner_segment(
|
|||
fn add_edge_segment(
|
||||
image_rect: LayoutRect,
|
||||
task_rect: DeviceRect,
|
||||
style: BorderStyle,
|
||||
color: ColorF,
|
||||
side: &BorderSide,
|
||||
segment: BorderSegment,
|
||||
edge_flags: EdgeAaSegmentMask,
|
||||
instances: &mut Vec<BorderInstance>,
|
||||
border_segments: &mut Vec<BorderSegmentInfo>,
|
||||
brush_flags: BrushFlags,
|
||||
brush_segments: &mut Vec<BrushSegment>,
|
||||
) {
|
||||
if color.a <= 0.0 {
|
||||
if side.color.a <= 0.0 {
|
||||
return;
|
||||
}
|
||||
|
||||
if style == BorderStyle::Hidden || style == BorderStyle::None {
|
||||
if side.style.is_hidden() {
|
||||
return;
|
||||
}
|
||||
|
||||
add_segment(
|
||||
border_segments.push(BorderSegmentInfo {
|
||||
task_rect,
|
||||
style,
|
||||
style,
|
||||
color,
|
||||
color,
|
||||
segment,
|
||||
instances,
|
||||
DeviceSize::zero(),
|
||||
DeviceSize::zero(),
|
||||
);
|
||||
radius: DeviceSize::zero(),
|
||||
widths: task_rect.size,
|
||||
});
|
||||
|
||||
add_brush_segment(
|
||||
image_rect,
|
||||
|
|
|
@ -8,10 +8,10 @@ use api::{ClipId, ColorF, ComplexClipRegion, DeviceIntPoint, DeviceIntRect, Devi
|
|||
use api::{DevicePixelScale, DeviceUintRect, DisplayItemRef, Epoch, ExtendMode, ExternalScrollId};
|
||||
use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, GlyphRasterSpace, GradientStop};
|
||||
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayoutPoint};
|
||||
use api::{LayoutPrimitiveInfo, LayoutRect, LayoutVector2D, LayoutSize, LayoutTransform};
|
||||
use api::{LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
|
||||
use api::{LineOrientation, LineStyle, LocalClip, NinePatchBorderSource, PipelineId};
|
||||
use api::{PropertyBinding, RepeatMode, ScrollFrameDisplayItem, ScrollSensitivity, Shadow};
|
||||
use api::{SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
|
||||
use api::{PropertyBinding, ReferenceFrame, RepeatMode, ScrollFrameDisplayItem, ScrollSensitivity};
|
||||
use api::{Shadow, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
|
||||
use api::{TransformStyle, YuvColorSpace, YuvData};
|
||||
use app_units::Au;
|
||||
use clip::{ClipRegion, ClipSource, ClipSources, ClipStore};
|
||||
|
@ -157,10 +157,6 @@ pub struct DisplayListFlattener<'a> {
|
|||
/// output textures.
|
||||
output_pipelines: &'a FastHashSet<PipelineId>,
|
||||
|
||||
/// A list of replacements to make in order to properly handle fixed position
|
||||
/// content as well as stacking contexts that create reference frames.
|
||||
replacements: Vec<(ClipId, ClipId)>,
|
||||
|
||||
/// The data structure that converting between ClipId and the various index
|
||||
/// types that the ClipScrollTree uses.
|
||||
id_to_index_mapper: ClipIdToIndexMapper,
|
||||
|
@ -225,7 +221,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
font_instances,
|
||||
config: *frame_builder_config,
|
||||
pipeline_epochs: Vec::new(),
|
||||
replacements: Vec::new(),
|
||||
output_pipelines,
|
||||
id_to_index_mapper: ClipIdToIndexMapper::default(),
|
||||
hit_testing_runs: recycle_vec(old_builder.hit_testing_runs),
|
||||
|
@ -263,17 +258,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
)
|
||||
}
|
||||
|
||||
/// Since WebRender still handles fixed position and reference frame content internally
|
||||
/// we need to apply this table of id replacements only to the id that affects the
|
||||
/// position of a node. We can eventually remove this when clients start handling
|
||||
/// reference frames themselves. This method applies these replacements.
|
||||
fn apply_scroll_frame_id_replacement(&self, index: ClipId) -> ClipId {
|
||||
match self.replacements.last() {
|
||||
Some(&(to_replace, replacement)) if to_replace == index => replacement,
|
||||
_ => index,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_complex_clips(
|
||||
&self,
|
||||
pipeline_id: PipelineId,
|
||||
|
@ -282,14 +266,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
if complex_clips.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
self.scene
|
||||
.pipelines
|
||||
.get(&pipeline_id)
|
||||
.expect("No display list?")
|
||||
.display_list
|
||||
.get(complex_clips)
|
||||
.collect()
|
||||
self.scene.get_display_list_for_pipeline(pipeline_id).get(complex_clips).collect()
|
||||
}
|
||||
|
||||
fn get_clip_chain_items(
|
||||
|
@ -300,14 +277,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
if items.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
self.scene
|
||||
.pipelines
|
||||
.get(&pipeline_id)
|
||||
.expect("No display list?")
|
||||
.display_list
|
||||
.get(items)
|
||||
.collect()
|
||||
self.scene.get_display_list_for_pipeline(pipeline_id).get(items).collect()
|
||||
}
|
||||
|
||||
fn flatten_root(&mut self, pipeline: &'a ScenePipeline, frame_size: &LayoutSize) {
|
||||
|
@ -379,6 +349,10 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
None => break,
|
||||
};
|
||||
|
||||
if SpecificDisplayItem::PopReferenceFrame == *item.item() {
|
||||
return;
|
||||
}
|
||||
|
||||
if SpecificDisplayItem::PopStackingContext == *item.item() {
|
||||
return;
|
||||
}
|
||||
|
@ -462,15 +436,37 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
fn flatten_reference_frame(
|
||||
&mut self,
|
||||
traversal: &mut BuiltDisplayListIter<'a>,
|
||||
pipeline_id: PipelineId,
|
||||
item: &DisplayItemRef,
|
||||
reference_frame: &ReferenceFrame,
|
||||
scroll_node_id: ClipId,
|
||||
reference_frame_relative_offset: LayoutVector2D,
|
||||
) {
|
||||
self.push_reference_frame(
|
||||
reference_frame.id,
|
||||
Some(scroll_node_id),
|
||||
pipeline_id,
|
||||
reference_frame.transform,
|
||||
reference_frame.perspective,
|
||||
reference_frame_relative_offset + item.rect().origin.to_vector(),
|
||||
);
|
||||
|
||||
self.flatten_items(traversal, pipeline_id, LayoutVector2D::zero());
|
||||
|
||||
self.pop_reference_frame();
|
||||
}
|
||||
|
||||
fn flatten_stacking_context(
|
||||
&mut self,
|
||||
traversal: &mut BuiltDisplayListIter<'a>,
|
||||
pipeline_id: PipelineId,
|
||||
item: &DisplayItemRef,
|
||||
stacking_context: &StackingContext,
|
||||
unreplaced_scroll_id: ClipId,
|
||||
scroll_node_id: ClipId,
|
||||
mut reference_frame_relative_offset: LayoutVector2D,
|
||||
reference_frame_relative_offset: LayoutVector2D,
|
||||
is_backface_visible: bool,
|
||||
) {
|
||||
// Avoid doing unnecessary work for empty stacking contexts.
|
||||
|
@ -481,52 +477,20 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
let composition_operations = {
|
||||
// TODO(optimization?): self.traversal.display_list()
|
||||
let display_list = &self
|
||||
.scene
|
||||
.pipelines
|
||||
.get(&pipeline_id)
|
||||
.expect("No display list?!")
|
||||
.display_list;
|
||||
let display_list = self.scene.get_display_list_for_pipeline(pipeline_id);
|
||||
CompositeOps::new(
|
||||
stacking_context.filter_ops_for_compositing(display_list, item.filters()),
|
||||
stacking_context.mix_blend_mode_for_compositing(),
|
||||
)
|
||||
};
|
||||
|
||||
let bounds = item.rect();
|
||||
reference_frame_relative_offset += bounds.origin.to_vector();
|
||||
|
||||
// If we have a transformation or a perspective, we should have been assigned a new
|
||||
// reference frame id. This means this stacking context establishes a new reference frame.
|
||||
// Descendant fixed position content will be positioned relative to us.
|
||||
if let Some(reference_frame_id) = stacking_context.reference_frame_id {
|
||||
debug_assert!(
|
||||
stacking_context.transform.is_some() ||
|
||||
stacking_context.perspective.is_some()
|
||||
);
|
||||
|
||||
self.push_reference_frame(
|
||||
reference_frame_id,
|
||||
Some(scroll_node_id),
|
||||
pipeline_id,
|
||||
stacking_context.transform,
|
||||
stacking_context.perspective,
|
||||
reference_frame_relative_offset,
|
||||
);
|
||||
self.replacements.push((unreplaced_scroll_id, reference_frame_id));
|
||||
reference_frame_relative_offset = LayoutVector2D::zero();
|
||||
}
|
||||
|
||||
// We apply the replacements one more time in case we need to set it to a replacement
|
||||
// that we just pushed above.
|
||||
let final_scroll_node = self.apply_scroll_frame_id_replacement(unreplaced_scroll_id);
|
||||
self.push_stacking_context(
|
||||
pipeline_id,
|
||||
composition_operations,
|
||||
stacking_context.transform_style,
|
||||
is_backface_visible,
|
||||
false,
|
||||
final_scroll_node,
|
||||
scroll_node_id,
|
||||
stacking_context.clip_node_id,
|
||||
stacking_context.glyph_raster_space,
|
||||
);
|
||||
|
@ -534,14 +498,9 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
self.flatten_items(
|
||||
traversal,
|
||||
pipeline_id,
|
||||
reference_frame_relative_offset,
|
||||
reference_frame_relative_offset + item.rect().origin.to_vector(),
|
||||
);
|
||||
|
||||
if stacking_context.reference_frame_id.is_some() {
|
||||
self.replacements.pop();
|
||||
self.pop_reference_frame();
|
||||
}
|
||||
|
||||
self.pop_stacking_context();
|
||||
}
|
||||
|
||||
|
@ -608,10 +567,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
pipeline_id: PipelineId,
|
||||
reference_frame_relative_offset: LayoutVector2D,
|
||||
) -> Option<BuiltDisplayListIter<'a>> {
|
||||
let mut clip_and_scroll_ids = item.clip_and_scroll();
|
||||
let unreplaced_scroll_id = clip_and_scroll_ids.scroll_node_id;
|
||||
clip_and_scroll_ids.scroll_node_id =
|
||||
self.apply_scroll_frame_id_replacement(clip_and_scroll_ids.scroll_node_id);
|
||||
let clip_and_scroll_ids = item.clip_and_scroll();
|
||||
let clip_and_scroll = self.id_to_index_mapper.map_clip_and_scroll(&clip_and_scroll_ids);
|
||||
|
||||
let prim_info = item.get_layout_primitive_info(&reference_frame_relative_offset);
|
||||
|
@ -733,13 +689,25 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
pipeline_id,
|
||||
&item,
|
||||
&info.stacking_context,
|
||||
unreplaced_scroll_id,
|
||||
clip_and_scroll_ids.scroll_node_id,
|
||||
reference_frame_relative_offset,
|
||||
prim_info.is_backface_visible,
|
||||
);
|
||||
return Some(subtraversal);
|
||||
}
|
||||
SpecificDisplayItem::PushReferenceFrame(ref info) => {
|
||||
let mut subtraversal = item.sub_iter();
|
||||
self.flatten_reference_frame(
|
||||
&mut subtraversal,
|
||||
pipeline_id,
|
||||
&item,
|
||||
&info.reference_frame,
|
||||
clip_and_scroll_ids.scroll_node_id,
|
||||
reference_frame_relative_offset,
|
||||
);
|
||||
return Some(subtraversal);
|
||||
|
||||
}
|
||||
SpecificDisplayItem::Iframe(ref info) => {
|
||||
self.flatten_iframe(
|
||||
&item,
|
||||
|
@ -792,7 +760,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// Do nothing; these are dummy items for the display list parser
|
||||
SpecificDisplayItem::SetGradientStops => {}
|
||||
|
||||
SpecificDisplayItem::PopStackingContext => {
|
||||
SpecificDisplayItem::PopStackingContext | SpecificDisplayItem::PopReferenceFrame => {
|
||||
unreachable!("Should have returned in parent method.")
|
||||
}
|
||||
SpecificDisplayItem::PushShadow(shadow) => {
|
||||
|
|
|
@ -81,7 +81,6 @@ unsafe impl Send for ThreadSafePathfinderFontContext {}
|
|||
unsafe impl Sync for ThreadSafePathfinderFontContext { }
|
||||
|
||||
impl GlyphRasterizer {
|
||||
|
||||
pub(in super) fn add_font_to_pathfinder(&mut self, font_key: &FontKey, template: &FontTemplate) {
|
||||
let font_contexts = Arc::clone(&self.font_contexts);
|
||||
debug!("add_font_to_pathfinder({:?})", font_key);
|
||||
|
@ -180,9 +179,7 @@ impl GlyphRasterizer {
|
|||
Entry::Vacant(_) => {}
|
||||
}
|
||||
|
||||
let cached_glyph_info = match cached_glyph_info {
|
||||
Some(cached_glyph_info) => cached_glyph_info,
|
||||
None => {
|
||||
if cached_glyph_info.is_none() {
|
||||
let mut pathfinder_font_context = self.font_contexts.lock_pathfinder_context();
|
||||
|
||||
let pathfinder_font_instance = pathfinder_font_renderer::FontInstance {
|
||||
|
@ -196,39 +193,40 @@ impl GlyphRasterizer {
|
|||
let pathfinder_glyph_key =
|
||||
pathfinder_font_renderer::GlyphKey::new(glyph_key.index,
|
||||
pathfinder_subpixel_offset);
|
||||
let glyph_dimensions =
|
||||
match pathfinder_font_context.glyph_dimensions(&pathfinder_font_instance,
|
||||
|
||||
if let Ok(glyph_dimensions) =
|
||||
pathfinder_font_context.glyph_dimensions(&pathfinder_font_instance,
|
||||
&pathfinder_glyph_key,
|
||||
false) {
|
||||
Ok(glyph_dimensions) => glyph_dimensions,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
let cached_glyph_info = CachedGlyphInfo {
|
||||
render_task_cache_key: RenderTaskCacheKey {
|
||||
let render_task_cache_key = RenderTaskCacheKey {
|
||||
size: TypedSize2D::from_untyped(&glyph_dimensions.size.to_i32()),
|
||||
kind: RenderTaskCacheKeyKind::Glyph(self.next_gpu_glyph_cache_key),
|
||||
},
|
||||
};
|
||||
cached_glyph_info = Some(CachedGlyphInfo {
|
||||
render_task_cache_key,
|
||||
format: font.get_glyph_format(),
|
||||
origin: DeviceIntPoint::new(glyph_dimensions.origin.x as i32,
|
||||
-glyph_dimensions.origin.y as i32),
|
||||
};
|
||||
});
|
||||
self.next_gpu_glyph_cache_key.0 += 1;
|
||||
cached_glyph_info
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let handle =
|
||||
let handle = match cached_glyph_info {
|
||||
Some(glyph_info) => {
|
||||
match self.request_glyph_from_pathfinder_if_necessary(glyph_key,
|
||||
&font,
|
||||
cached_glyph_info.clone(),
|
||||
glyph_info.clone(),
|
||||
texture_cache,
|
||||
gpu_cache,
|
||||
render_task_cache,
|
||||
render_task_tree,
|
||||
render_passes) {
|
||||
Ok(_) => GlyphCacheEntry::Cached(cached_glyph_info),
|
||||
Ok(_) => GlyphCacheEntry::Cached(glyph_info),
|
||||
Err(_) => GlyphCacheEntry::Blank,
|
||||
}
|
||||
}
|
||||
None => GlyphCacheEntry::Blank,
|
||||
};
|
||||
|
||||
glyph_key_cache.insert(glyph_key.clone(), handle);
|
||||
|
|
|
@ -1469,6 +1469,7 @@ impl PrimitiveStore {
|
|||
let scale = world_scale * frame_context.device_pixel_scale;
|
||||
let scale_au = Au::from_f32_px(scale.0);
|
||||
let needs_update = scale_au != cache_key.scale;
|
||||
let mut new_segments = Vec::new();
|
||||
|
||||
if needs_update {
|
||||
cache_key.scale = scale_au;
|
||||
|
@ -1478,6 +1479,7 @@ impl PrimitiveStore {
|
|||
border,
|
||||
widths,
|
||||
scale,
|
||||
&mut new_segments,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -1495,7 +1497,7 @@ impl PrimitiveStore {
|
|||
|render_tasks| {
|
||||
let task = RenderTask::new_border(
|
||||
task_info.size,
|
||||
task_info.instances.clone(),
|
||||
task_info.build_instances(border),
|
||||
);
|
||||
|
||||
let task_id = render_tasks.add(task);
|
||||
|
@ -1508,7 +1510,7 @@ impl PrimitiveStore {
|
|||
|
||||
if needs_update {
|
||||
brush.segment_desc = Some(BrushSegmentDescriptor {
|
||||
segments: task_info.segments.clone(),
|
||||
segments: new_segments,
|
||||
clip_mask_kind: BrushClipMaskKind::Unknown,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1190,26 +1190,28 @@ trait ToDebugString {
|
|||
impl ToDebugString for SpecificDisplayItem {
|
||||
fn debug_string(&self) -> String {
|
||||
match *self {
|
||||
SpecificDisplayItem::Image(..) => String::from("image"),
|
||||
SpecificDisplayItem::YuvImage(..) => String::from("yuv_image"),
|
||||
SpecificDisplayItem::Text(..) => String::from("text"),
|
||||
SpecificDisplayItem::Rectangle(..) => String::from("rectangle"),
|
||||
SpecificDisplayItem::ClearRectangle => String::from("clear_rectangle"),
|
||||
SpecificDisplayItem::Line(..) => String::from("line"),
|
||||
SpecificDisplayItem::Gradient(..) => String::from("gradient"),
|
||||
SpecificDisplayItem::RadialGradient(..) => String::from("radial_gradient"),
|
||||
SpecificDisplayItem::BoxShadow(..) => String::from("box_shadow"),
|
||||
SpecificDisplayItem::Border(..) => String::from("border"),
|
||||
SpecificDisplayItem::PushStackingContext(..) => String::from("push_stacking_context"),
|
||||
SpecificDisplayItem::Iframe(..) => String::from("iframe"),
|
||||
SpecificDisplayItem::BoxShadow(..) => String::from("box_shadow"),
|
||||
SpecificDisplayItem::ClearRectangle => String::from("clear_rectangle"),
|
||||
SpecificDisplayItem::Clip(..) => String::from("clip"),
|
||||
SpecificDisplayItem::ClipChain(..) => String::from("clip_chain"),
|
||||
SpecificDisplayItem::ScrollFrame(..) => String::from("scroll_frame"),
|
||||
SpecificDisplayItem::StickyFrame(..) => String::from("sticky_frame"),
|
||||
SpecificDisplayItem::SetGradientStops => String::from("set_gradient_stops"),
|
||||
SpecificDisplayItem::PopStackingContext => String::from("pop_stacking_context"),
|
||||
SpecificDisplayItem::PushShadow(..) => String::from("push_shadow"),
|
||||
SpecificDisplayItem::Gradient(..) => String::from("gradient"),
|
||||
SpecificDisplayItem::Iframe(..) => String::from("iframe"),
|
||||
SpecificDisplayItem::Image(..) => String::from("image"),
|
||||
SpecificDisplayItem::Line(..) => String::from("line"),
|
||||
SpecificDisplayItem::PopAllShadows => String::from("pop_all_shadows"),
|
||||
SpecificDisplayItem::PopReferenceFrame => String::from("pop_reference_frame"),
|
||||
SpecificDisplayItem::PopStackingContext => String::from("pop_stacking_context"),
|
||||
SpecificDisplayItem::PushReferenceFrame(..) => String::from("push_reference_frame"),
|
||||
SpecificDisplayItem::PushShadow(..) => String::from("push_shadow"),
|
||||
SpecificDisplayItem::PushStackingContext(..) => String::from("push_stacking_context"),
|
||||
SpecificDisplayItem::RadialGradient(..) => String::from("radial_gradient"),
|
||||
SpecificDisplayItem::Rectangle(..) => String::from("rectangle"),
|
||||
SpecificDisplayItem::ScrollFrame(..) => String::from("scroll_frame"),
|
||||
SpecificDisplayItem::SetGradientStops => String::from("set_gradient_stops"),
|
||||
SpecificDisplayItem::StickyFrame(..) => String::from("sticky_frame"),
|
||||
SpecificDisplayItem::Text(..) => String::from("text"),
|
||||
SpecificDisplayItem::YuvImage(..) => String::from("yuv_image"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -701,7 +701,13 @@ impl RenderTask {
|
|||
}
|
||||
};
|
||||
|
||||
let (target_rect, target_index) = self.get_target_rect();
|
||||
let (mut target_rect, target_index) = self.get_target_rect();
|
||||
// The primitives inside a fixed-location render task
|
||||
// are already placed to their corresponding positions,
|
||||
// so the shader doesn't need to shift by the origin.
|
||||
if let RenderTaskLocation::Fixed(_) = self.location {
|
||||
target_rect.origin = DeviceIntPoint::origin();
|
||||
};
|
||||
|
||||
RenderTaskData {
|
||||
data: [
|
||||
|
|
|
@ -2887,8 +2887,18 @@ impl Renderer {
|
|||
|
||||
for alpha_batch_container in &target.alpha_batch_containers {
|
||||
if let Some(target_rect) = alpha_batch_container.target_rect {
|
||||
// Note: `framebuffer_target_rect` needs a Y-flip before going to GL
|
||||
let rect = if render_target.is_none() {
|
||||
let mut rect = target_rect
|
||||
.intersection(&framebuffer_target_rect.to_i32())
|
||||
.unwrap_or(DeviceIntRect::zero());
|
||||
rect.origin.y = target_size.height as i32 - rect.origin.y - rect.size.height;
|
||||
rect
|
||||
} else {
|
||||
target_rect
|
||||
};
|
||||
self.device.enable_scissor();
|
||||
self.device.set_scissor_rect(target_rect);
|
||||
self.device.set_scissor_rect(rect);
|
||||
}
|
||||
|
||||
// Draw opaque batches front-to-back for maximum
|
||||
|
@ -2930,8 +2940,18 @@ impl Renderer {
|
|||
|
||||
for alpha_batch_container in &target.alpha_batch_containers {
|
||||
if let Some(target_rect) = alpha_batch_container.target_rect {
|
||||
// Note: `framebuffer_target_rect` needs a Y-flip before going to GL
|
||||
let rect = if render_target.is_none() {
|
||||
let mut rect = target_rect
|
||||
.intersection(&framebuffer_target_rect.to_i32())
|
||||
.unwrap_or(DeviceIntRect::zero());
|
||||
rect.origin.y = target_size.height as i32 - rect.origin.y - rect.size.height;
|
||||
rect
|
||||
} else {
|
||||
target_rect
|
||||
};
|
||||
self.device.enable_scissor();
|
||||
self.device.set_scissor_rect(target_rect);
|
||||
self.device.set_scissor_rect(rect);
|
||||
}
|
||||
|
||||
for batch in &alpha_batch_container.alpha_batches {
|
||||
|
|
|
@ -662,6 +662,7 @@ impl ResourceCache {
|
|||
if let Some(dirty) = dirty_rect {
|
||||
if intersect_for_tile(dirty, actual_size, tile_size, tile_offset).is_none() {
|
||||
// don't bother requesting unchanged tiles
|
||||
self.pending_image_requests.remove(&request);
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,6 +115,13 @@ impl Scene {
|
|||
self.root_pipeline_id = Some(pipeline_id);
|
||||
}
|
||||
|
||||
pub fn get_display_list_for_pipeline(&self, pipeline_id: PipelineId) -> &BuiltDisplayList {
|
||||
&self.pipelines
|
||||
.get(&pipeline_id)
|
||||
.expect("Expected to find display list for pipeline")
|
||||
.display_list
|
||||
}
|
||||
|
||||
pub fn set_display_list(
|
||||
&mut self,
|
||||
pipeline_id: PipelineId,
|
||||
|
|
|
@ -109,6 +109,8 @@ pub enum SpecificDisplayItem {
|
|||
Iframe(IframeDisplayItem),
|
||||
PushStackingContext(PushStackingContextDisplayItem),
|
||||
PopStackingContext,
|
||||
PushReferenceFrame(PushReferenceFrameDisplayListItem),
|
||||
PopReferenceFrame,
|
||||
SetGradientStops,
|
||||
PushShadow(Shadow),
|
||||
PopAllShadows,
|
||||
|
@ -138,6 +140,8 @@ pub enum CompletelySpecificDisplayItem {
|
|||
Iframe(IframeDisplayItem),
|
||||
PushStackingContext(PushStackingContextDisplayItem, Vec<FilterOp>),
|
||||
PopStackingContext,
|
||||
PushReferenceFrame(PushReferenceFrameDisplayListItem),
|
||||
PopReferenceFrame,
|
||||
SetGradientStops(Vec<GradientStop>),
|
||||
PushShadow(Shadow),
|
||||
PopAllShadows,
|
||||
|
@ -386,6 +390,12 @@ pub enum BorderStyle {
|
|||
Outset = 9,
|
||||
}
|
||||
|
||||
impl BorderStyle {
|
||||
pub fn is_hidden(&self) -> bool {
|
||||
*self == BorderStyle::Hidden || *self == BorderStyle::None
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum BoxShadowClipMode {
|
||||
|
@ -462,6 +472,18 @@ pub struct RadialGradientDisplayItem {
|
|||
pub tile_spacing: LayoutSize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct PushReferenceFrameDisplayListItem {
|
||||
pub reference_frame: ReferenceFrame,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ReferenceFrame {
|
||||
pub transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
pub perspective: Option<LayoutTransform>,
|
||||
pub id: ClipId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct PushStackingContextDisplayItem {
|
||||
pub stacking_context: StackingContext,
|
||||
|
@ -469,11 +491,8 @@ pub struct PushStackingContextDisplayItem {
|
|||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct StackingContext {
|
||||
pub transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
pub transform_style: TransformStyle,
|
||||
pub perspective: Option<LayoutTransform>,
|
||||
pub mix_blend_mode: MixBlendMode,
|
||||
pub reference_frame_id: Option<ClipId>,
|
||||
pub clip_node_id: Option<ClipId>,
|
||||
pub glyph_raster_space: GlyphRasterSpace,
|
||||
} // IMPLICIT: filters: Vec<FilterOp>
|
||||
|
|
|
@ -20,10 +20,11 @@ use {FontInstanceKey, GlyphInstance, GlyphOptions, GlyphRasterSpace, Gradient};
|
|||
use {GradientDisplayItem, GradientStop, IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask};
|
||||
use {ImageRendering, LayoutPoint, LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform};
|
||||
use {LayoutVector2D, LineDisplayItem, LineOrientation, LineStyle, MixBlendMode, PipelineId};
|
||||
use {PropertyBinding, PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
|
||||
use {RectangleDisplayItem, ScrollFrameDisplayItem, ScrollSensitivity, Shadow, SpecificDisplayItem};
|
||||
use {StackingContext, StickyFrameDisplayItem, StickyOffsetBounds, TextDisplayItem, TransformStyle};
|
||||
use {YuvColorSpace, YuvData, YuvImageDisplayItem};
|
||||
use {PropertyBinding, PushReferenceFrameDisplayListItem, PushStackingContextDisplayItem};
|
||||
use {RadialGradient, RadialGradientDisplayItem, RectangleDisplayItem, ReferenceFrame};
|
||||
use {ScrollFrameDisplayItem, ScrollSensitivity, Shadow, SpecificDisplayItem, StackingContext};
|
||||
use {StickyFrameDisplayItem, StickyOffsetBounds, TextDisplayItem, TransformStyle, YuvColorSpace};
|
||||
use {YuvData, YuvImageDisplayItem};
|
||||
|
||||
// We don't want to push a long text-run. If a text-run is too long, split it into several parts.
|
||||
// This needs to be set to (renderer::MAX_VERTEX_TEXTURE_WIDTH - VECS_PER_PRIM_HEADER - VECS_PER_TEXT_RUN) * 2
|
||||
|
@ -481,6 +482,8 @@ impl Serialize for BuiltDisplayList {
|
|||
item.iter.list.get(item.iter.cur_filters).collect()
|
||||
),
|
||||
SpecificDisplayItem::PopStackingContext => PopStackingContext,
|
||||
SpecificDisplayItem::PushReferenceFrame(v) => PushReferenceFrame(v),
|
||||
SpecificDisplayItem::PopReferenceFrame => PopReferenceFrame,
|
||||
SpecificDisplayItem::SetGradientStops => SetGradientStops(
|
||||
item.iter.list.get(item.iter.cur_stops).collect()
|
||||
),
|
||||
|
@ -555,13 +558,15 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
|||
SpecificDisplayItem::Iframe(specific_item)
|
||||
}
|
||||
PushStackingContext(specific_item, filters) => {
|
||||
if specific_item.stacking_context.reference_frame_id.is_some() {
|
||||
total_clip_ids += 1;
|
||||
}
|
||||
DisplayListBuilder::push_iter_impl(&mut temp, filters);
|
||||
SpecificDisplayItem::PushStackingContext(specific_item)
|
||||
},
|
||||
PopStackingContext => SpecificDisplayItem::PopStackingContext,
|
||||
PushReferenceFrame(specific_item) => {
|
||||
total_clip_ids += 1;
|
||||
SpecificDisplayItem::PushReferenceFrame(specific_item)
|
||||
}
|
||||
PopReferenceFrame => SpecificDisplayItem::PopReferenceFrame,
|
||||
SetGradientStops(stops) => {
|
||||
DisplayListBuilder::push_iter_impl(&mut temp, stops);
|
||||
SpecificDisplayItem::SetGradientStops
|
||||
|
@ -1277,30 +1282,41 @@ impl DisplayListBuilder {
|
|||
self.push_item(item, info);
|
||||
}
|
||||
|
||||
pub fn push_reference_frame(
|
||||
&mut self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
perspective: Option<LayoutTransform>,
|
||||
) -> ClipId {
|
||||
let id = self.generate_clip_id();
|
||||
let item = SpecificDisplayItem::PushReferenceFrame(PushReferenceFrameDisplayListItem {
|
||||
reference_frame: ReferenceFrame {
|
||||
transform,
|
||||
perspective,
|
||||
id,
|
||||
},
|
||||
});
|
||||
self.push_item(item, info);
|
||||
id
|
||||
}
|
||||
|
||||
pub fn pop_reference_frame(&mut self) {
|
||||
self.push_new_empty_item(SpecificDisplayItem::PopReferenceFrame);
|
||||
}
|
||||
|
||||
pub fn push_stacking_context(
|
||||
&mut self,
|
||||
info: &LayoutPrimitiveInfo,
|
||||
clip_node_id: Option<ClipId>,
|
||||
transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
transform_style: TransformStyle,
|
||||
perspective: Option<LayoutTransform>,
|
||||
mix_blend_mode: MixBlendMode,
|
||||
filters: Vec<FilterOp>,
|
||||
glyph_raster_space: GlyphRasterSpace,
|
||||
) -> Option<ClipId> {
|
||||
let reference_frame_id = if transform.is_some() || perspective.is_some() {
|
||||
Some(self.generate_clip_id())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
) {
|
||||
let item = SpecificDisplayItem::PushStackingContext(PushStackingContextDisplayItem {
|
||||
stacking_context: StackingContext {
|
||||
transform,
|
||||
transform_style,
|
||||
perspective,
|
||||
mix_blend_mode,
|
||||
reference_frame_id,
|
||||
clip_node_id,
|
||||
glyph_raster_space,
|
||||
},
|
||||
|
@ -1308,8 +1324,6 @@ impl DisplayListBuilder {
|
|||
|
||||
self.push_item(item, info);
|
||||
self.push_iter(&filters);
|
||||
|
||||
reference_frame_id
|
||||
}
|
||||
|
||||
pub fn pop_stacking_context(&mut self) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
3829687ffbe8d55885d71a3d5e5e79216251548f
|
||||
8e697f8cb1f1aab2e5f6b9b903eb7191340b10c5
|
||||
|
|
|
@ -154,6 +154,13 @@ impl<'a> RawtestHarness<'a> {
|
|||
Some(31),
|
||||
);
|
||||
|
||||
let called = Arc::new(AtomicIsize::new(0));
|
||||
let called_inner = Arc::clone(&called);
|
||||
|
||||
self.wrench.callbacks.lock().unwrap().request = Box::new(move |_| {
|
||||
called_inner.fetch_add(1, Ordering::SeqCst);
|
||||
});
|
||||
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
|
||||
let info = LayoutPrimitiveInfo::new(rect(0., -9600.0, 1510.000031, 111256.));
|
||||
|
@ -178,13 +185,6 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
self.submit_dl(&mut epoch, layout_size, builder, &txn.resource_updates);
|
||||
|
||||
let called = Arc::new(AtomicIsize::new(0));
|
||||
let called_inner = Arc::clone(&called);
|
||||
|
||||
self.wrench.callbacks.lock().unwrap().request = Box::new(move |_| {
|
||||
called_inner.fetch_add(1, Ordering::SeqCst);
|
||||
});
|
||||
|
||||
let pixels = self.render_and_get_pixels(window_rect);
|
||||
|
||||
// make sure we didn't request too many blobs
|
||||
|
@ -225,6 +225,8 @@ impl<'a> RawtestHarness<'a> {
|
|||
txn = Transaction::new();
|
||||
txn.delete_image(blob_img);
|
||||
self.wrench.api.update_resources(txn.resource_updates);
|
||||
|
||||
*self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new();
|
||||
}
|
||||
|
||||
fn test_offscreen_blob(&mut self) {
|
||||
|
@ -362,6 +364,13 @@ impl<'a> RawtestHarness<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
let called = Arc::new(AtomicIsize::new(0));
|
||||
let called_inner = Arc::clone(&called);
|
||||
|
||||
self.wrench.callbacks.lock().unwrap().request = Box::new(move |_| {
|
||||
assert_eq!(0, called_inner.fetch_add(1, Ordering::SeqCst));
|
||||
});
|
||||
|
||||
// draw the blob the first time
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
let info = LayoutPrimitiveInfo::new(rect(0.0, 60.0, 200.0, 200.0));
|
||||
|
@ -379,16 +388,9 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
self.submit_dl(&mut epoch, layout_size, builder, &txn.resource_updates);
|
||||
|
||||
let called = Arc::new(AtomicIsize::new(0));
|
||||
let called_inner = Arc::clone(&called);
|
||||
|
||||
self.wrench.callbacks.lock().unwrap().request = Box::new(move |_| {
|
||||
called_inner.fetch_add(1, Ordering::SeqCst);
|
||||
});
|
||||
|
||||
let pixels_first = self.render_and_get_pixels(window_rect);
|
||||
|
||||
assert!(called.load(Ordering::SeqCst) == 1);
|
||||
assert_eq!(1, called.load(Ordering::SeqCst));
|
||||
|
||||
// draw the blob image a second time at a different location
|
||||
|
||||
|
@ -411,13 +413,16 @@ impl<'a> RawtestHarness<'a> {
|
|||
let pixels_second = self.render_and_get_pixels(window_rect);
|
||||
|
||||
// make sure we only requested once
|
||||
assert!(called.load(Ordering::SeqCst) == 1);
|
||||
assert_eq!(1, called.load(Ordering::SeqCst));
|
||||
|
||||
// use png;
|
||||
// png::save_flipped("out1.png", &pixels_first, window_rect.size);
|
||||
// png::save_flipped("out2.png", &pixels_second, window_rect.size);
|
||||
|
||||
assert!(pixels_first != pixels_second);
|
||||
|
||||
// cleanup
|
||||
*self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new();
|
||||
}
|
||||
|
||||
fn test_blob_update_epoch_test(&mut self) {
|
||||
|
@ -539,6 +544,9 @@ impl<'a> RawtestHarness<'a> {
|
|||
assert_eq!(img1_requested.load(Ordering::SeqCst), 3);
|
||||
// the second image should've been requested twice
|
||||
assert_eq!(img2_requested.load(Ordering::SeqCst), 2);
|
||||
|
||||
// cleanup
|
||||
*self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new();
|
||||
}
|
||||
|
||||
fn test_blob_update_test(&mut self) {
|
||||
|
|
|
@ -1254,6 +1254,26 @@ impl YamlFrameReader {
|
|||
Some(self.to_complex_clip_region(complex_clip))
|
||||
}
|
||||
|
||||
pub fn get_item_type_from_yaml(item: &Yaml) -> &str {
|
||||
let shorthands = [
|
||||
"rect",
|
||||
"image",
|
||||
"text",
|
||||
"glyphs",
|
||||
"box-shadow", // Note: box_shadow shorthand check has to come before border.
|
||||
"border",
|
||||
"gradient",
|
||||
"radial-gradient",
|
||||
];
|
||||
|
||||
for shorthand in shorthands.iter() {
|
||||
if !item[*shorthand].is_badvalue() {
|
||||
return shorthand;
|
||||
}
|
||||
}
|
||||
item["type"].as_str().unwrap_or("unknown")
|
||||
}
|
||||
|
||||
pub fn add_display_list_items_from_yaml(
|
||||
&mut self,
|
||||
dl: &mut DisplayListBuilder,
|
||||
|
@ -1268,32 +1288,13 @@ impl YamlFrameReader {
|
|||
LayoutSize::new(big_number, big_number));
|
||||
|
||||
for item in yaml.as_vec().unwrap() {
|
||||
// an explicit type can be skipped with some shorthand
|
||||
let item_type = if !item["rect"].is_badvalue() {
|
||||
"rect"
|
||||
} else if !item["image"].is_badvalue() {
|
||||
"image"
|
||||
} else if !item["text"].is_badvalue() {
|
||||
"text"
|
||||
} else if !item["glyphs"].is_badvalue() {
|
||||
"glyphs"
|
||||
} else if !item["box-shadow"].is_badvalue() {
|
||||
// Note: box_shadow shorthand check has to come before border.
|
||||
"box-shadow"
|
||||
} else if !item["border"].is_badvalue() {
|
||||
"border"
|
||||
} else if !item["gradient"].is_badvalue() {
|
||||
"gradient"
|
||||
} else if !item["radial-gradient"].is_badvalue() {
|
||||
"radial-gradient"
|
||||
} else {
|
||||
item["type"].as_str().unwrap_or("unknown")
|
||||
};
|
||||
let item_type = Self::get_item_type_from_yaml(item);
|
||||
|
||||
// We never skip stacking contexts because they are structural elements
|
||||
// of the display list.
|
||||
if item_type != "stacking-context" && self.include_only.contains(&item_type.to_owned())
|
||||
{
|
||||
// We never skip stacking contexts and reference frames because
|
||||
// they are structural elements of the display list.
|
||||
if item_type != "stacking-context" &&
|
||||
item_type != "reference-frame" &&
|
||||
self.include_only.contains(&item_type.to_owned()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1343,6 +1344,7 @@ impl YamlFrameReader {
|
|||
"stacking-context" => {
|
||||
self.add_stacking_context_from_yaml(dl, wrench, item, false, &mut info)
|
||||
}
|
||||
"reference-frame" => self.handle_reference_frame(dl, wrench, item, &mut info),
|
||||
"shadow" => self.handle_push_shadow(dl, item, &mut info),
|
||||
"pop-all-shadows" => self.handle_pop_all_shadows(dl),
|
||||
_ => println!("Skipping unknown item type: {:?}", item),
|
||||
|
@ -1503,22 +1505,22 @@ impl YamlFrameReader {
|
|||
.unwrap_or(wrench.window_size_f32())
|
||||
}
|
||||
|
||||
pub fn add_stacking_context_from_yaml(
|
||||
pub fn push_reference_frame(
|
||||
&mut self,
|
||||
dl: &mut DisplayListBuilder,
|
||||
wrench: &mut Wrench,
|
||||
yaml: &Yaml,
|
||||
is_root: bool,
|
||||
info: &mut LayoutPrimitiveInfo,
|
||||
) {
|
||||
) -> ClipId {
|
||||
let default_bounds = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32());
|
||||
let bounds = yaml["bounds"].as_rect().unwrap_or(default_bounds);
|
||||
|
||||
let default_transform_origin = LayoutPoint::new(
|
||||
bounds.origin.x + bounds.size.width * 0.5,
|
||||
bounds.origin.y + bounds.size.height * 0.5,
|
||||
);
|
||||
|
||||
info.rect = bounds;
|
||||
|
||||
let transform_origin = yaml["transform-origin"]
|
||||
.as_point()
|
||||
.unwrap_or(default_transform_origin);
|
||||
|
@ -1531,8 +1533,6 @@ impl YamlFrameReader {
|
|||
.as_transform(&transform_origin)
|
||||
.map(|transform| transform.into());
|
||||
|
||||
let clip_node_id = self.to_clip_id(&yaml["clip-node"], dl.pipeline_id);
|
||||
|
||||
let perspective = match yaml["perspective"].as_f32() {
|
||||
Some(value) if value != 0.0 => {
|
||||
Some(make_perspective(perspective_origin, value as f32))
|
||||
|
@ -1541,6 +1541,58 @@ impl YamlFrameReader {
|
|||
_ => yaml["perspective"].as_matrix4d(),
|
||||
};
|
||||
|
||||
let reference_frame_id = dl.push_reference_frame(info, transform.into(), perspective);
|
||||
|
||||
let numeric_id = yaml["reference-frame-id"].as_i64();
|
||||
if let Some(numeric_id) = numeric_id {
|
||||
self.add_clip_id_mapping(numeric_id as u64, reference_frame_id);
|
||||
}
|
||||
|
||||
reference_frame_id
|
||||
}
|
||||
|
||||
pub fn handle_reference_frame(
|
||||
&mut self,
|
||||
dl: &mut DisplayListBuilder,
|
||||
wrench: &mut Wrench,
|
||||
yaml: &Yaml,
|
||||
info: &mut LayoutPrimitiveInfo,
|
||||
) {
|
||||
let reference_frame_id = self.push_reference_frame(dl, wrench, yaml, info);
|
||||
|
||||
if !yaml["items"].is_badvalue() {
|
||||
dl.push_clip_id(reference_frame_id);
|
||||
self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
|
||||
dl.pop_clip_id();
|
||||
}
|
||||
|
||||
dl.pop_reference_frame();
|
||||
}
|
||||
|
||||
pub fn add_stacking_context_from_yaml(
|
||||
&mut self,
|
||||
dl: &mut DisplayListBuilder,
|
||||
wrench: &mut Wrench,
|
||||
yaml: &Yaml,
|
||||
is_root: bool,
|
||||
info: &mut LayoutPrimitiveInfo,
|
||||
) {
|
||||
let default_bounds = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32());
|
||||
let bounds = yaml["bounds"].as_rect().unwrap_or(default_bounds);
|
||||
info.rect = bounds;
|
||||
info.clip_rect = bounds;
|
||||
|
||||
let reference_frame_id = if !yaml["transform"].is_badvalue() ||
|
||||
!yaml["perspective"].is_badvalue() {
|
||||
let reference_frame_id = self.push_reference_frame(dl, wrench, yaml, info);
|
||||
info.rect.origin = LayoutPoint::zero();
|
||||
info.clip_rect.origin = LayoutPoint::zero();
|
||||
Some(reference_frame_id)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let clip_node_id = self.to_clip_id(&yaml["clip-node"], dl.pipeline_id);
|
||||
let transform_style = yaml["transform-style"]
|
||||
.as_transform_style()
|
||||
.unwrap_or(TransformStyle::Flat);
|
||||
|
@ -1559,33 +1611,33 @@ impl YamlFrameReader {
|
|||
}
|
||||
|
||||
let filters = yaml["filters"].as_vec_filter_op().unwrap_or(vec![]);
|
||||
info.rect = bounds;
|
||||
info.clip_rect = bounds;
|
||||
|
||||
let reference_frame_id = dl.push_stacking_context(
|
||||
if let Some(reference_frame_id) = reference_frame_id {
|
||||
dl.push_clip_id(reference_frame_id);
|
||||
}
|
||||
|
||||
dl.push_stacking_context(
|
||||
&info,
|
||||
clip_node_id,
|
||||
transform.into(),
|
||||
transform_style,
|
||||
perspective,
|
||||
mix_blend_mode,
|
||||
filters,
|
||||
glyph_raster_space,
|
||||
);
|
||||
|
||||
let numeric_id = yaml["reference-frame-id"].as_i64();
|
||||
match (numeric_id, reference_frame_id) {
|
||||
(Some(numeric_id), Some(reference_frame_id)) => {
|
||||
self.add_clip_id_mapping(numeric_id as u64, reference_frame_id);
|
||||
}
|
||||
_ => {},
|
||||
}
|
||||
|
||||
if !yaml["items"].is_badvalue() {
|
||||
self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
|
||||
}
|
||||
|
||||
dl.pop_stacking_context();
|
||||
|
||||
if reference_frame_id.is_some() {
|
||||
dl.pop_clip_id();
|
||||
}
|
||||
|
||||
if reference_frame_id.is_some() {
|
||||
dl.pop_reference_frame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,6 +178,25 @@ fn maybe_radius_yaml(radius: &BorderRadius) -> Option<Yaml> {
|
|||
}
|
||||
}
|
||||
|
||||
fn write_reference_frame(
|
||||
parent: &mut Table,
|
||||
reference_frame: &ReferenceFrame,
|
||||
properties: &SceneProperties,
|
||||
clip_id_mapper: &mut ClipIdMapper,
|
||||
) {
|
||||
matrix4d_node(
|
||||
parent,
|
||||
"transform",
|
||||
&properties.resolve_layout_transform(&reference_frame.transform)
|
||||
);
|
||||
|
||||
if let Some(perspective) = reference_frame.perspective {
|
||||
matrix4d_node(parent, "perspective", &perspective);
|
||||
}
|
||||
|
||||
usize_node(parent, "id", clip_id_mapper.add_id(reference_frame.id));
|
||||
}
|
||||
|
||||
fn write_stacking_context(
|
||||
parent: &mut Table,
|
||||
sc: &StackingContext,
|
||||
|
@ -185,8 +204,6 @@ fn write_stacking_context(
|
|||
filter_iter: AuxIter<FilterOp>,
|
||||
clip_id_mapper: &ClipIdMapper,
|
||||
) {
|
||||
matrix4d_node(parent, "transform", &properties.resolve_layout_transform(&sc.transform));
|
||||
|
||||
enum_node(parent, "transform-style", sc.transform_style);
|
||||
|
||||
let glyph_raster_space = match sc.glyph_raster_space {
|
||||
|
@ -203,10 +220,6 @@ fn write_stacking_context(
|
|||
yaml_node(parent, "clip-node", clip_id_mapper.map_id(&clip_node_id));
|
||||
}
|
||||
|
||||
if let Some(perspective) = sc.perspective {
|
||||
matrix4d_node(parent, "perspective", &perspective);
|
||||
}
|
||||
|
||||
// mix_blend_mode
|
||||
if sc.mix_blend_mode != MixBlendMode::Normal {
|
||||
enum_node(parent, "mix-blend-mode", sc.mix_blend_mode)
|
||||
|
@ -1031,6 +1044,19 @@ impl YamlFrameWriter {
|
|||
self.write_display_list(&mut v, display_list, scene, &mut sub_iter, clip_id_mapper);
|
||||
continue_traversal = Some(sub_iter);
|
||||
}
|
||||
PushReferenceFrame(item) => {
|
||||
str_node(&mut v, "type", "reference-frame");
|
||||
write_reference_frame(
|
||||
&mut v,
|
||||
&item.reference_frame,
|
||||
&scene.properties,
|
||||
clip_id_mapper
|
||||
);
|
||||
|
||||
let mut sub_iter = base.sub_iter();
|
||||
self.write_display_list(&mut v, display_list, scene, &mut sub_iter, clip_id_mapper);
|
||||
continue_traversal = Some(sub_iter);
|
||||
}
|
||||
Clip(item) => {
|
||||
str_node(&mut v, "type", "clip");
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_id(item.id));
|
||||
|
@ -1121,6 +1147,7 @@ impl YamlFrameWriter {
|
|||
}
|
||||
|
||||
PopStackingContext => return,
|
||||
PopReferenceFrame => return,
|
||||
SetGradientStops => panic!("dummy item yielded?"),
|
||||
PushShadow(shadow) => {
|
||||
str_node(&mut v, "type", "shadow");
|
||||
|
|
Загрузка…
Ссылка в новой задаче