mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1904891 - Support viewport and screen options for non-scaling-stroke r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D215138
This commit is contained in:
parent
36d5b49752
commit
9416db8add
@ -201,7 +201,9 @@ bool SVGGeometryElement::IsPointInStroke(const DOMPointInit& aPoint) {
|
||||
SVGGeometryProperty::DoForComputedStyle(this, [&](const ComputedStyle* s) {
|
||||
// Per spec, we should take vector-effect into account.
|
||||
if (s->StyleSVGReset()->HasNonScalingStroke()) {
|
||||
auto mat = SVGContentUtils::GetCTM(this);
|
||||
auto mat = s->StyleSVGReset()->mVectorEffect.IsScreen()
|
||||
? SVGContentUtils::GetScreenCTM(this)
|
||||
: SVGContentUtils::GetCTM(this);
|
||||
if (mat.HasNonTranslation()) {
|
||||
// We have non-scaling-stroke as well as a non-translation transform.
|
||||
// We should transform the path first then apply the stroke on the
|
||||
|
@ -174,7 +174,6 @@ rusty-enums = [
|
||||
"mozilla::StyleMaskMode",
|
||||
"mozilla::StyleScrollBehavior",
|
||||
"mozilla::StyleColorInterpolation",
|
||||
"mozilla::StyleVectorEffect",
|
||||
"mozilla::StyleBackfaceVisibility",
|
||||
"mozilla::StyleBlend",
|
||||
"mozilla::StyleMaskComposite",
|
||||
@ -588,6 +587,9 @@ cbindgen-types = [
|
||||
{ gecko = "StylePageOrientation", servo = "crate::values::generics::page::PageOrientation" },
|
||||
{ gecko = "StylePageSize", servo = "crate::values::computed::page::PageSize" },
|
||||
{ gecko = "StyleDProperty", servo = "crate::values::specified::svg::DProperty" },
|
||||
{ gecko = "StyleVectorEffectType", servo = "crate::values::specified::svg::VectorEffectType" },
|
||||
{ gecko = "StyleCoordinateSpace", servo = "crate::values::specified::svg::CoordinateSpace" },
|
||||
{ gecko = "StyleVectorEffect", servo = "crate::values::specified::svg::VectorEffect" },
|
||||
{ gecko = "StyleImageRendering", servo = "crate::values::computed::ImageRendering" },
|
||||
{ gecko = "StylePrintColorAdjust", servo = "crate::values::computed::PrintColorAdjust" },
|
||||
{ gecko = "StyleForcedColorAdjust", servo = "crate::values::computed::ForcedColorAdjust" },
|
||||
|
@ -555,9 +555,6 @@ enum class StyleColorInterpolation : uint8_t {
|
||||
Linearrgb = 2,
|
||||
};
|
||||
|
||||
// vector-effect
|
||||
enum class StyleVectorEffect : uint8_t { None = 0, NonScalingStroke = 1 };
|
||||
|
||||
// 3d Transforms - Backface visibility
|
||||
enum class StyleBackfaceVisibility : uint8_t { Hidden = 0, Visible = 1 };
|
||||
|
||||
|
@ -909,7 +909,6 @@ nsStyleSVGReset::nsStyleSVGReset()
|
||||
mLightingColor(StyleColor::White()),
|
||||
mStopOpacity(1.0f),
|
||||
mFloodOpacity(1.0f),
|
||||
mVectorEffect(StyleVectorEffect::None),
|
||||
mMaskType(StyleMaskType::Luminance),
|
||||
mD(StyleDProperty::None()) {
|
||||
MOZ_COUNT_CTOR(nsStyleSVGReset);
|
||||
|
@ -1912,7 +1912,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVGReset {
|
||||
bool HasMask() const;
|
||||
|
||||
bool HasNonScalingStroke() const {
|
||||
return mVectorEffect == mozilla::StyleVectorEffect::NonScalingStroke;
|
||||
return mVectorEffect.HasNonScalingStroke();
|
||||
}
|
||||
|
||||
// geometry properties
|
||||
|
@ -9787,8 +9787,18 @@ var gCSSProperties = {
|
||||
applies_to_first_letter: true,
|
||||
applies_to_first_line: true,
|
||||
initial_values: ["none"],
|
||||
other_values: ["non-scaling-stroke"],
|
||||
invalid_values: [],
|
||||
other_values: [
|
||||
"non-scaling-stroke",
|
||||
"non-scaling-stroke viewport",
|
||||
"non-scaling-stroke screen",
|
||||
],
|
||||
invalid_values: [
|
||||
"none non-scaling-stroke",
|
||||
"non-scaling-stroke viewport screen",
|
||||
"none viewport",
|
||||
"none screen",
|
||||
"viewport non-scaling-stroke",
|
||||
],
|
||||
},
|
||||
"-moz-window-dragging": {
|
||||
domProp: "MozWindowDragging",
|
||||
|
@ -1078,8 +1078,11 @@ bool SVGUtils::GetNonScalingStrokeTransform(const nsIFrame* aFrame,
|
||||
|
||||
MOZ_ASSERT(aFrame->GetContent()->IsSVGElement(), "should be an SVG element");
|
||||
|
||||
*aUserToOuterSVG = ThebesMatrix(
|
||||
SVGContentUtils::GetCTM(static_cast<SVGElement*>(aFrame->GetContent())));
|
||||
SVGElement* content = static_cast<SVGElement*>(aFrame->GetContent());
|
||||
*aUserToOuterSVG =
|
||||
ThebesMatrix(aFrame->StyleSVGReset()->mVectorEffect.IsScreen()
|
||||
? SVGContentUtils::GetScreenCTM(content)
|
||||
: SVGContentUtils::GetCTM(content));
|
||||
|
||||
return aUserToOuterSVG->HasNonTranslation() && !aUserToOuterSVG->IsSingular();
|
||||
}
|
||||
|
@ -617,6 +617,7 @@ class Longhand(Property):
|
||||
"TouchAction",
|
||||
"TransformStyle",
|
||||
"UserSelect",
|
||||
"VectorEffect",
|
||||
"WordBreak",
|
||||
"XSpan",
|
||||
"XTextScale",
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
<%namespace name="helpers" file="/helpers.mako.rs" />
|
||||
|
||||
${helpers.single_keyword(
|
||||
${helpers.predefined_type(
|
||||
"vector-effect",
|
||||
"none non-scaling-stroke",
|
||||
"VectorEffect",
|
||||
"computed::VectorEffect::none()",
|
||||
engines="gecko",
|
||||
gecko_enum_prefix="StyleVectorEffect",
|
||||
animation_value_type="discrete",
|
||||
spec="https://svgwg.org/svg2-draft/coords.html#VectorEffects",
|
||||
affects="layout",
|
||||
|
@ -104,7 +104,7 @@ pub use self::rect::NonNegativeLengthOrNumberRect;
|
||||
pub use self::resolution::Resolution;
|
||||
pub use self::svg::{DProperty, MozContextProperties};
|
||||
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
|
||||
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
|
||||
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth, VectorEffect};
|
||||
pub use self::text::HyphenateCharacter;
|
||||
pub use self::text::TextUnderlinePosition;
|
||||
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, TextIndent};
|
||||
|
@ -10,7 +10,7 @@ use crate::values::computed::{LengthPercentage, NonNegativeLengthPercentage, Opa
|
||||
use crate::values::generics::svg as generic;
|
||||
use crate::Zero;
|
||||
|
||||
pub use crate::values::specified::{DProperty, MozContextProperties, SVGPaintOrder};
|
||||
pub use crate::values::specified::{DProperty, MozContextProperties, SVGPaintOrder, VectorEffect};
|
||||
|
||||
/// Computed SVG Paint value
|
||||
pub type SVGPaint = generic::GenericSVGPaint<Color, ComputedUrl>;
|
||||
|
@ -96,7 +96,7 @@ pub use self::rect::NonNegativeLengthOrNumberRect;
|
||||
pub use self::resolution::Resolution;
|
||||
pub use self::svg::{DProperty, MozContextProperties};
|
||||
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint};
|
||||
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
|
||||
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth, VectorEffect};
|
||||
pub use self::svg_path::SVGPathData;
|
||||
pub use self::text::HyphenateCharacter;
|
||||
pub use self::text::RubyPosition;
|
||||
|
@ -402,3 +402,122 @@ impl Parse for DProperty {
|
||||
Ok(DProperty::Path(path_data))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Default,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
Parse,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[css(bitflags(single = "none", mixed = "non-scaling-stroke"))]
|
||||
#[repr(C)]
|
||||
/// Values for vector-effect:
|
||||
/// https://svgwg.org/svg2-draft/coords.html#VectorEffects
|
||||
pub struct VectorEffectType(u8);
|
||||
bitflags! {
|
||||
impl VectorEffectType: u8 {
|
||||
/// `none`
|
||||
const NONE = 0;
|
||||
/// `non-scaling-stroke`
|
||||
const NON_SCALING_STROKE = 1 << 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
impl VectorEffectType {
|
||||
pub fn is_none(&self) -> bool {
|
||||
*self == VectorEffectType::NONE
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Default,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
Parse,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
/// co-ordinate space for vector-effect:
|
||||
/// https://svgwg.org/svg2-draft/coords.html#VectorEffects
|
||||
pub enum CoordinateSpace {
|
||||
#[default]
|
||||
/// `viewport`
|
||||
Viewport,
|
||||
/// `screen`
|
||||
Screen,
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
impl CoordinateSpace {
|
||||
pub fn is_viewport(&self) -> bool {
|
||||
*self == Self::Viewport
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToCss,
|
||||
ToComputedValue,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
/// Specified value for the vector-effect property.
|
||||
/// (The spec grammar gives
|
||||
/// `none | [ non-scaling-stroke | non-scaling-size | non-rotation | fixed-position ]+ [ viewport | screen ]?`.)
|
||||
/// https://svgwg.org/svg2-draft/coords.html#VectorEffects
|
||||
pub struct VectorEffect {
|
||||
/// none or non-scaling-stroke
|
||||
pub effect_type: VectorEffectType,
|
||||
/// screen or viewport
|
||||
#[css(skip_if = "CoordinateSpace::is_viewport")]
|
||||
pub coordinate_space: CoordinateSpace,
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
impl VectorEffect {
|
||||
#[inline]
|
||||
pub fn none() -> Self {
|
||||
Self {
|
||||
effect_type: VectorEffectType::NONE,
|
||||
coordinate_space: CoordinateSpace::Viewport,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for VectorEffect {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let effect_type = VectorEffectType::parse(context, input)?;
|
||||
if effect_type.is_none() {
|
||||
return Ok(Self::none());
|
||||
}
|
||||
let coordinate_space = input.try_parse(CoordinateSpace::parse).unwrap_or(CoordinateSpace::Viewport);
|
||||
Ok(Self { effect_type, coordinate_space })
|
||||
}
|
||||
}
|
||||
|
@ -307,6 +307,7 @@ include = [
|
||||
"ComputedLinearStop",
|
||||
"PiecewiseLinearFunction",
|
||||
"BeforeFlag",
|
||||
"VectorEffect",
|
||||
"XTextScale",
|
||||
"Zoom",
|
||||
"TransitionProperty",
|
||||
@ -555,6 +556,15 @@ renaming_overrides_prefixing = true
|
||||
inline bool IsRight() const;
|
||||
"""
|
||||
|
||||
"VectorEffect" = """
|
||||
StyleVectorEffect()
|
||||
: effect_type(StyleVectorEffectType::NONE),
|
||||
coordinate_space(StyleCoordinateSpace::Viewport) {}
|
||||
|
||||
bool HasNonScalingStroke() const { return bool(effect_type & StyleVectorEffectType::NON_SCALING_STROKE); }
|
||||
bool IsScreen() const { return coordinate_space == StyleCoordinateSpace::Screen; }
|
||||
"""
|
||||
|
||||
# TODO(emilio): Add hooks to cbindgen to be able to generate [[nodiscard]]
|
||||
# on the functions.
|
||||
"Owned" = """
|
||||
|
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<title>non-scaling-stroke with screen transform</title>
|
||||
<link rel="help" href="https://svgwg.org/svg2-draft/painting.html#PaintingVectorEffects" />
|
||||
<link rel="match" href="green-100x100.svg" />
|
||||
<body>
|
||||
<style>
|
||||
body {
|
||||
border: none;
|
||||
margin: 0;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
transform: scale(0.5);
|
||||
}
|
||||
svg {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
transform: scale(2) translate(-25px, -25px);
|
||||
transform-origin: center;
|
||||
transform-bxox: fill-box;
|
||||
}
|
||||
rect {
|
||||
fill: red;
|
||||
stroke: green;
|
||||
stroke-width: 75px;
|
||||
vector-effect: non-scaling-stroke screen;
|
||||
}
|
||||
</style>
|
||||
<svg>
|
||||
<rect width="75" height="75"/>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>vector-effect test: parsing vector-effect with invalid values</title>
|
||||
<link rel="help" href="https://www.w3.org/TR/SVG2/coords.html#VectorEffects">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_invalid_value("vector-effect", "none none");
|
||||
test_invalid_value("vector-effect", "none non-scaling-stroke");
|
||||
test_invalid_value("vector-effect", "non-scaling-stroke viewport screen");
|
||||
test_invalid_value("vector-effect", "none viewport");
|
||||
test_invalid_value("vector-effect", "none screen");
|
||||
test_invalid_value("vector-effect", "viewport");
|
||||
test_invalid_value("vector-effect", "screen");
|
||||
test_invalid_value("vector-effect", "screen non-scaling-stroke");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>vector-effect test: parsing vector-effect with invalid values</title>
|
||||
<link rel="help" href="https://www.w3.org/TR/SVG2/coords.html#VectorEffects">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_valid_value("vector-effect", "none");
|
||||
test_valid_value("vector-effect", "non-scaling-stroke");
|
||||
test_valid_value("vector-effect", "non-scaling-stroke viewport", "non-scaling-stroke");
|
||||
test_valid_value("vector-effect", "non-scaling-stroke screen");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user