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

Support different radii and elliptical radii in box shadows. #1889

Merged
merged 1 commit into from Oct 18, 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

@@ -339,7 +339,7 @@ impl Example for App {
color,
blur_radius,
spread_radius,
simple_border_radius,
BorderRadius::uniform(simple_border_radius),
box_shadow_type,
);
}
@@ -14,12 +14,15 @@ flat varying vec4 vClipCenter_Radius_BL;

struct BrushPrimitive {
float clip_mode;
float radius;
vec2 radius_tl;
vec2 radius_tr;
vec2 radius_br;
vec2 radius_bl;
};

BrushPrimitive fetch_brush_primitive(int address) {
vec4 data = fetch_from_resource_cache_1(address);
return BrushPrimitive(data.x, data.y);
vec4 data[3] = fetch_from_resource_cache_3(address);
return BrushPrimitive(data[0].x, data[1].xy, data[1].zw, data[2].xy, data[2].zw);
}

void brush_vs(int prim_address, vec4 prim_rect) {
@@ -29,11 +32,10 @@ void brush_vs(int prim_address, vec4 prim_rect) {
// Write clip parameters
vClipMode = prim.clip_mode;

vec2 r = vec2(prim.radius);
vClipCenter_Radius_TL = vec4(prim_rect.xy + vec2(r.x, r.y), r);
vClipCenter_Radius_TR = vec4(prim_rect.zy + vec2(-r.x, r.y), r);
vClipCenter_Radius_BR = vec4(prim_rect.zw + vec2(-r.x, -r.y), r);
vClipCenter_Radius_BL = vec4(prim_rect.xw + vec2(r.x, -r.y), r);
vClipCenter_Radius_TL = vec4(prim_rect.xy + prim.radius_tl, prim.radius_tl);
vClipCenter_Radius_TR = vec4(prim_rect.zy + vec2(-prim.radius_tr.x, prim.radius_tr.y), prim.radius_tr);
vClipCenter_Radius_BR = vec4(prim_rect.zw - prim.radius_br, prim.radius_br);
vClipCenter_Radius_BL = vec4(prim_rect.xw + vec2(prim.radius_bl.x, -prim.radius_bl.y), prim.radius_bl);
}
#endif

@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode, BuiltDisplayList};
use api::{ComplexClipRegion, ClipAndScrollInfo, ClipId, ColorF};
use api::{ComplexClipRegion, ClipAndScrollInfo, ClipId, ColorF, LayoutSize};
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize};
use api::{ExtendMode, FilterOp, FontInstance, FontRenderMode};
use api::{GlyphInstance, GlyphOptions, GradientStop, HitTestFlags, HitTestItem, HitTestResult};
@@ -1258,7 +1258,7 @@ impl FrameBuilder {
color: &ColorF,
blur_radius: f32,
spread_radius: f32,
border_radius: f32,
border_radius: BorderRadius,
clip_mode: BoxShadowClipMode,
) {
if color.a == 0.0 {
@@ -1274,15 +1274,11 @@ impl FrameBuilder {
}
};

// Adjust the shadow box radius as per:
// https://drafts.csswg.org/css-backgrounds-3/#shadow-shape
let sharpness_scale = if border_radius < spread_radius {
let r = border_radius / spread_amount;
1.0 + (r - 1.0) * (r - 1.0) * (r - 1.0)
} else {
1.0
};
let shadow_radius = (border_radius + spread_amount * sharpness_scale).max(0.0);
let shadow_radius = adjust_border_radius_for_box_shadow(
border_radius,
spread_amount,
spread_radius
);
let shadow_rect = prim_info.rect
.translate(box_offset)
.inflate(spread_amount, spread_amount);
@@ -1295,30 +1291,30 @@ impl FrameBuilder {
// TODO(gw): Add a fast path for ClipOut + zero border radius!
clips.push(ClipSource::RoundedRectangle(
prim_info.rect,
BorderRadius::uniform(border_radius),
border_radius,
ClipMode::ClipOut
));

LayerPrimitiveInfo::with_clip(
shadow_rect,
LocalClip::RoundedRect(
shadow_rect,
ComplexClipRegion::new(shadow_rect, BorderRadius::uniform(shadow_radius)),
ComplexClipRegion::new(shadow_rect, shadow_radius),
),
)
}
BoxShadowClipMode::Inset => {
clips.push(ClipSource::RoundedRectangle(
shadow_rect,
BorderRadius::uniform(shadow_radius),
shadow_radius,
ClipMode::ClipOut
));

LayerPrimitiveInfo::with_clip(
prim_info.rect,
LocalClip::RoundedRect(
prim_info.rect,
ComplexClipRegion::new(prim_info.rect, BorderRadius::uniform(border_radius)),
ComplexClipRegion::new(prim_info.rect, border_radius),
),
)
}
@@ -1366,7 +1362,7 @@ impl FrameBuilder {

extra_clips.push(ClipSource::RoundedRectangle(
prim_info.rect,
BorderRadius::uniform(border_radius),
border_radius,
ClipMode::ClipOut,
));

@@ -1396,7 +1392,7 @@ impl FrameBuilder {

extra_clips.push(ClipSource::RoundedRectangle(
prim_info.rect,
BorderRadius::uniform(border_radius),
border_radius,
ClipMode::Clip,
));

@@ -2326,3 +2322,67 @@ impl FrameBuilder {
}
}
}

fn adjust_border_radius_for_box_shadow(
radius: BorderRadius,
spread_amount: f32,
spread_radius: f32,
) -> BorderRadius {
BorderRadius {
top_left: adjust_corner_for_box_shadow(
radius.top_left,
spread_radius,
spread_amount,
),
top_right: adjust_corner_for_box_shadow(
radius.top_right,
spread_radius,
spread_amount,
),
bottom_right: adjust_corner_for_box_shadow(
radius.bottom_right,
spread_radius,
spread_amount,
),
bottom_left: adjust_corner_for_box_shadow(
radius.bottom_left,
spread_radius,
spread_amount,
),
}
}

fn adjust_corner_for_box_shadow(
corner: LayoutSize,
spread_amount: f32,
spread_radius: f32,
) -> LayoutSize {
LayoutSize::new(
adjust_radius_for_box_shadow(
corner.width,
spread_radius,
spread_amount
),
adjust_radius_for_box_shadow(
corner.height,
spread_radius,
spread_amount
),
)
}

fn adjust_radius_for_box_shadow(
border_radius: f32,
spread_amount: f32,
spread_radius: f32,
) -> f32 {
// Adjust the shadow box radius as per:
// https://drafts.csswg.org/css-backgrounds-3/#shadow-shape
let sharpness_scale = if border_radius < spread_radius {
let r = border_radius / spread_amount;
1.0 + (r - 1.0) * (r - 1.0) * (r - 1.0)
} else {
1.0
};
(border_radius + spread_amount * sharpness_scale).max(0.0)
}
@@ -167,17 +167,29 @@ impl ToGpuBlocks for RectanglePrimitive {
#[derive(Debug)]
pub struct BrushPrimitive {
pub clip_mode: ClipMode,
pub radius: f32,
pub radius: BorderRadius,
}

impl ToGpuBlocks for BrushPrimitive {
fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
request.push([
self.clip_mode as u32 as f32,
self.radius,
0.0,
0.0,
0.0
]);
request.push([
self.radius.top_left.width,
self.radius.top_left.height,
self.radius.top_right.width,
self.radius.top_right.height,
]);
request.push([
self.radius.bottom_right.width,
self.radius.bottom_right.height,
self.radius.bottom_left.width,
self.radius.bottom_left.height,
]);
}
}

@@ -297,7 +297,7 @@ pub struct BoxShadowDisplayItem {
pub color: ColorF,
pub blur_radius: f32,
pub spread_radius: f32,
pub border_radius: f32,
pub border_radius: BorderRadius,
pub clip_mode: BoxShadowClipMode,
}

@@ -12,7 +12,7 @@ use {LineDisplayItem, LineOrientation, LineStyle, LocalClip, MixBlendMode, Pipel
use {PropertyBinding, PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
use {RectangleDisplayItem, ScrollFrameDisplayItem, ScrollPolicy, ScrollSensitivity};
use {SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, StickyFrameInfo};
use {TextDisplayItem, Shadow, TransformStyle, YuvColorSpace, YuvData};
use {BorderRadius, TextDisplayItem, Shadow, TransformStyle, YuvColorSpace, YuvData};
use YuvImageDisplayItem;
use bincode;
use serde::{Deserialize, Serialize, Serializer};
@@ -1024,7 +1024,7 @@ impl DisplayListBuilder {
color: ColorF,
blur_radius: f32,
spread_radius: f32,
border_radius: f32,
border_radius: BorderRadius,
clip_mode: BoxShadowClipMode,
) {
let item = SpecificDisplayItem::BoxShadow(BoxShadowDisplayItem {
Binary file not shown.
@@ -0,0 +1,36 @@
---
root:
items:
- type: stacking-context
bounds: [0, 0, 1000, 1000]
items:
- type: box-shadow
bounds: [ 50, 50, 100, 100 ]
color: red
clip-mode: outset
blur-radius: 10
border-radius: {
top-left: [20, 30],
top-right: [10, 30],
bottom-left: [50, 25],
bottom-right: [0, 0],
}

- type: box-shadow
bounds: [ 200, 50, 100, 100 ]
color: green
clip-mode: inset
blur-radius: 10
border-radius: {
top-left: [20, 30],
top-right: [10, 30],
bottom-left: [50, 25],
bottom-right: [0, 0],
}

- type: box-shadow
bounds: [ 350, 50, 100, 100 ]
color: blue
clip-mode: outset
blur-radius: 10
border-radius: [ 10, 20, 30, 40 ]
@@ -8,4 +8,5 @@ fuzzy(1,396) == inset-large-offset.yaml inset-large-offset-ref.png
== box-shadow-suite-no-blur.yaml box-shadow-suite-no-blur.png
== box-shadow-suite-blur.yaml box-shadow-suite-blur.png
== rounding.yaml rounding-ref.yaml
== box-shadow-border-radii.yaml box-shadow-border-radii.png

@@ -834,7 +834,9 @@ impl YamlFrameReader {
.unwrap_or(ColorF::new(0.0, 0.0, 0.0, 1.0));
let blur_radius = item["blur-radius"].as_force_f32().unwrap_or(0.0);
let spread_radius = item["spread-radius"].as_force_f32().unwrap_or(0.0);
let border_radius = item["border-radius"].as_force_f32().unwrap_or(0.0);
let border_radius = item["border-radius"]
.as_border_radius()
.unwrap_or(BorderRadius::zero());
let clip_mode = if let Some(mode) = item["clip-mode"].as_str() {
match mode {
"outset" => BoxShadowClipMode::Outset,
@@ -894,7 +894,9 @@ impl YamlFrameWriter {
color_node(&mut v, "color", item.color);
f32_node(&mut v, "blur-radius", item.blur_radius);
f32_node(&mut v, "spread-radius", item.spread_radius);
f32_node(&mut v, "border-radius", item.border_radius);
if let Some(radius_node) = maybe_radius_yaml(&item.border_radius) {
yaml_node(&mut v, "border-radius", radius_node);
}
let clip_mode = match item.clip_mode {
BoxShadowClipMode::Outset => "outset",
BoxShadowClipMode::Inset => "inset",
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.