Skip to content

Commit 199c72d

Browse files
committed
Avoid drawing empty border edges
1 parent df73569 commit 199c72d

File tree

1 file changed

+107
-121
lines changed

1 file changed

+107
-121
lines changed

webrender/src/border.rs

+107-121
Original file line numberDiff line numberDiff line change
@@ -103,134 +103,116 @@ pub enum BorderEdgeKind {
103103
Clip,
104104
}
105105

106-
trait NormalBorderHelpers {
107-
fn get_corner(
108-
&self,
109-
edge0: &BorderSide,
110-
width0: f32,
111-
edge1: &BorderSide,
112-
width1: f32,
113-
radius: &LayerSize,
114-
corner: BorderCorner,
115-
border_rect: &LayerRect,
116-
) -> BorderCornerKind;
106+
fn get_corner(
107+
edge0: &BorderSide,
108+
width0: f32,
109+
edge1: &BorderSide,
110+
width1: f32,
111+
radius: &LayerSize,
112+
corner: BorderCorner,
113+
border_rect: &LayerRect,
114+
) -> BorderCornerKind {
115+
// If both widths are zero, a corner isn't formed.
116+
if width0 == 0.0 && width1 == 0.0 {
117+
return BorderCornerKind::None;
118+
}
117119

118-
fn get_edge(&self, edge: &BorderSide, width: f32) -> (BorderEdgeKind, f32);
119-
}
120+
// If both edges are transparent, no corner is formed.
121+
if edge0.color.a == 0.0 && edge1.color.a == 0.0 {
122+
return BorderCornerKind::None;
123+
}
120124

121-
impl NormalBorderHelpers for NormalBorder {
122-
fn get_corner(
123-
&self,
124-
edge0: &BorderSide,
125-
width0: f32,
126-
edge1: &BorderSide,
127-
width1: f32,
128-
radius: &LayerSize,
129-
corner: BorderCorner,
130-
border_rect: &LayerRect,
131-
) -> BorderCornerKind {
132-
// If both widths are zero, a corner isn't formed.
133-
if width0 == 0.0 && width1 == 0.0 {
134-
return BorderCornerKind::None;
125+
match (edge0.style, edge1.style) {
126+
// If both edges are none or hidden, no corner is needed.
127+
(BorderStyle::None, BorderStyle::None) |
128+
(BorderStyle::None, BorderStyle::Hidden) |
129+
(BorderStyle::Hidden, BorderStyle::None) |
130+
(BorderStyle::Hidden, BorderStyle::Hidden) => {
131+
BorderCornerKind::None
135132
}
136133

137-
// If both edges are transparent, no corner is formed.
138-
if edge0.color.a == 0.0 && edge1.color.a == 0.0 {
139-
return BorderCornerKind::None;
134+
// If one of the edges is none or hidden, we just draw one style.
135+
(BorderStyle::None, _) |
136+
(_, BorderStyle::None) |
137+
(BorderStyle::Hidden, _) |
138+
(_, BorderStyle::Hidden) => {
139+
BorderCornerKind::Clip(BorderCornerInstance::Single)
140140
}
141141

142-
match (edge0.style, edge1.style) {
143-
// If both edges are none or hidden, no corner is needed.
144-
(BorderStyle::None, BorderStyle::None) |
145-
(BorderStyle::None, BorderStyle::Hidden) |
146-
(BorderStyle::Hidden, BorderStyle::None) |
147-
(BorderStyle::Hidden, BorderStyle::Hidden) => {
148-
BorderCornerKind::None
149-
}
150-
151-
// If one of the edges is none or hidden, we just draw one style.
152-
(BorderStyle::None, _) |
153-
(_, BorderStyle::None) |
154-
(BorderStyle::Hidden, _) |
155-
(_, BorderStyle::Hidden) => {
156-
BorderCornerKind::Clip(BorderCornerInstance::Single)
157-
}
158-
159-
// If both borders are solid, we can draw them with a simple rectangle if
160-
// both the colors match and there is no radius.
161-
(BorderStyle::Solid, BorderStyle::Solid) => {
162-
if edge0.color == edge1.color && radius.width == 0.0 && radius.height == 0.0 {
163-
BorderCornerKind::Solid
164-
} else {
165-
BorderCornerKind::Clip(BorderCornerInstance::Single)
166-
}
167-
}
168-
169-
// Inset / outset borders just modify the color of edges, so can be
170-
// drawn with the normal border corner shader.
171-
(BorderStyle::Outset, BorderStyle::Outset) |
172-
(BorderStyle::Inset, BorderStyle::Inset) |
173-
(BorderStyle::Double, BorderStyle::Double) |
174-
(BorderStyle::Groove, BorderStyle::Groove) |
175-
(BorderStyle::Ridge, BorderStyle::Ridge) => {
142+
// If both borders are solid, we can draw them with a simple rectangle if
143+
// both the colors match and there is no radius.
144+
(BorderStyle::Solid, BorderStyle::Solid) => {
145+
if edge0.color == edge1.color && radius.width == 0.0 && radius.height == 0.0 {
146+
BorderCornerKind::Solid
147+
} else {
176148
BorderCornerKind::Clip(BorderCornerInstance::Single)
177149
}
178-
179-
// Dashed and dotted border corners get drawn into a clip mask.
180-
(BorderStyle::Dashed, BorderStyle::Dashed) => BorderCornerKind::new_mask(
181-
BorderCornerClipKind::Dash,
182-
width0,
183-
width1,
184-
corner,
185-
*radius,
186-
*border_rect,
187-
),
188-
(BorderStyle::Dotted, BorderStyle::Dotted) => BorderCornerKind::new_mask(
189-
BorderCornerClipKind::Dot,
190-
width0,
191-
width1,
192-
corner,
193-
*radius,
194-
*border_rect,
195-
),
196-
197-
// Draw border transitions with dots and/or dashes as
198-
// solid segments. The old border path didn't support
199-
// this anyway, so we might as well start using the new
200-
// border path here, since the dashing in the edges is
201-
// much higher quality anyway.
202-
(BorderStyle::Dotted, _) |
203-
(_, BorderStyle::Dotted) |
204-
(BorderStyle::Dashed, _) |
205-
(_, BorderStyle::Dashed) => BorderCornerKind::Clip(BorderCornerInstance::Single),
206-
207-
// Everything else can be handled by drawing the corner twice,
208-
// where the shader outputs zero alpha for the side it's not
209-
// drawing. This is somewhat inefficient in terms of pixels
210-
// written, but it's a fairly rare case, and we can optimize
211-
// this case later.
212-
_ => BorderCornerKind::Clip(BorderCornerInstance::Double),
213150
}
214-
}
215151

216-
fn get_edge(&self, edge: &BorderSide, width: f32) -> (BorderEdgeKind, f32) {
217-
if width == 0.0 {
218-
return (BorderEdgeKind::None, 0.0);
152+
// Inset / outset borders just modify the color of edges, so can be
153+
// drawn with the normal border corner shader.
154+
(BorderStyle::Outset, BorderStyle::Outset) |
155+
(BorderStyle::Inset, BorderStyle::Inset) |
156+
(BorderStyle::Double, BorderStyle::Double) |
157+
(BorderStyle::Groove, BorderStyle::Groove) |
158+
(BorderStyle::Ridge, BorderStyle::Ridge) => {
159+
BorderCornerKind::Clip(BorderCornerInstance::Single)
219160
}
220161

221-
match edge.style {
222-
BorderStyle::None | BorderStyle::Hidden => (BorderEdgeKind::None, 0.0),
162+
// Dashed and dotted border corners get drawn into a clip mask.
163+
(BorderStyle::Dashed, BorderStyle::Dashed) => BorderCornerKind::new_mask(
164+
BorderCornerClipKind::Dash,
165+
width0,
166+
width1,
167+
corner,
168+
*radius,
169+
*border_rect,
170+
),
171+
(BorderStyle::Dotted, BorderStyle::Dotted) => BorderCornerKind::new_mask(
172+
BorderCornerClipKind::Dot,
173+
width0,
174+
width1,
175+
corner,
176+
*radius,
177+
*border_rect,
178+
),
179+
180+
// Draw border transitions with dots and/or dashes as
181+
// solid segments. The old border path didn't support
182+
// this anyway, so we might as well start using the new
183+
// border path here, since the dashing in the edges is
184+
// much higher quality anyway.
185+
(BorderStyle::Dotted, _) |
186+
(_, BorderStyle::Dotted) |
187+
(BorderStyle::Dashed, _) |
188+
(_, BorderStyle::Dashed) => BorderCornerKind::Clip(BorderCornerInstance::Single),
189+
190+
// Everything else can be handled by drawing the corner twice,
191+
// where the shader outputs zero alpha for the side it's not
192+
// drawing. This is somewhat inefficient in terms of pixels
193+
// written, but it's a fairly rare case, and we can optimize
194+
// this case later.
195+
_ => BorderCornerKind::Clip(BorderCornerInstance::Double),
196+
}
197+
}
198+
199+
fn get_edge(edge: &BorderSide, width: f32, height: f32) -> (BorderEdgeKind, f32) {
200+
if width == 0.0 || height <= 0.0 {
201+
return (BorderEdgeKind::None, 0.0);
202+
}
223203

224-
BorderStyle::Solid | BorderStyle::Inset | BorderStyle::Outset => {
225-
(BorderEdgeKind::Solid, width)
226-
}
204+
match edge.style {
205+
BorderStyle::None | BorderStyle::Hidden => (BorderEdgeKind::None, 0.0),
227206

228-
BorderStyle::Double |
229-
BorderStyle::Groove |
230-
BorderStyle::Ridge |
231-
BorderStyle::Dashed |
232-
BorderStyle::Dotted => (BorderEdgeKind::Clip, width),
207+
BorderStyle::Solid | BorderStyle::Inset | BorderStyle::Outset => {
208+
(BorderEdgeKind::Solid, width)
233209
}
210+
211+
BorderStyle::Double |
212+
BorderStyle::Groove |
213+
BorderStyle::Ridge |
214+
BorderStyle::Dashed |
215+
BorderStyle::Dotted => (BorderEdgeKind::Clip, width),
234216
}
235217
}
236218

@@ -431,7 +413,7 @@ impl<'a> DisplayListFlattener<'a> {
431413
}
432414

433415
let corners = [
434-
border.get_corner(
416+
get_corner(
435417
left,
436418
widths.left,
437419
top,
@@ -440,7 +422,7 @@ impl<'a> DisplayListFlattener<'a> {
440422
BorderCorner::TopLeft,
441423
&info.rect,
442424
),
443-
border.get_corner(
425+
get_corner(
444426
right,
445427
widths.right,
446428
top,
@@ -449,7 +431,7 @@ impl<'a> DisplayListFlattener<'a> {
449431
BorderCorner::TopRight,
450432
&info.rect,
451433
),
452-
border.get_corner(
434+
get_corner(
453435
right,
454436
widths.right,
455437
bottom,
@@ -458,7 +440,7 @@ impl<'a> DisplayListFlattener<'a> {
458440
BorderCorner::BottomRight,
459441
&info.rect,
460442
),
461-
border.get_corner(
443+
get_corner(
462444
left,
463445
widths.left,
464446
bottom,
@@ -469,10 +451,14 @@ impl<'a> DisplayListFlattener<'a> {
469451
),
470452
];
471453

472-
let (left_edge, left_len) = border.get_edge(left, widths.left);
473-
let (top_edge, top_len) = border.get_edge(top, widths.top);
474-
let (right_edge, right_len) = border.get_edge(right, widths.right);
475-
let (bottom_edge, bottom_len) = border.get_edge(bottom, widths.bottom);
454+
let (left_edge, left_len) = get_edge(left, widths.left,
455+
info.rect.size.height - radius.top_left.height - radius.bottom_left.height);
456+
let (top_edge, top_len) = get_edge(top, widths.top,
457+
info.rect.size.width - radius.top_left.width - radius.top_right.width);
458+
let (right_edge, right_len) = get_edge(right, widths.right,
459+
info.rect.size.height - radius.top_right.height - radius.bottom_right.height);
460+
let (bottom_edge, bottom_len) = get_edge(bottom, widths.bottom,
461+
info.rect.size.width - radius.bottom_right.width - radius.bottom_left.width);
476462

477463
let edges = [left_edge, top_edge, right_edge, bottom_edge];
478464

0 commit comments

Comments
 (0)