mirror of
https://github.com/servo/servo.git
synced 2025-07-13 10:23:40 +01:00
Servo currently uses `heapsize`, but Stylo/Gecko use `malloc_size_of`. `malloc_size_of` is better -- it handles various cases that `heapsize` does not -- so this patch changes Servo to use `malloc_size_of`. This patch makes the following changes to the `malloc_size_of` crate. - Adds `MallocSizeOf` trait implementations for numerous types, some built-in (e.g. `VecDeque`), some external and Servo-only (e.g. `string_cache`). - Makes `enclosing_size_of_op` optional, because vanilla jemalloc doesn't support that operation. - For `HashSet`/`HashMap`, falls back to a computed estimate when `enclosing_size_of_op` isn't available. - Adds an extern "C" `malloc_size_of` function that does the actual heap measurement; this is based on the same functions from the `heapsize` crate. This patch makes the following changes elsewhere. - Converts all the uses of `heapsize` to instead use `malloc_size_of`. - Disables the "heapsize"/"heap_size" feature for the external crates that provide it. - Removes the `HeapSizeOf` implementation from `hashglobe`. - Adds `ignore` annotations to a few `Rc`/`Arc`, because `malloc_size_of` doesn't derive those types, unlike `heapsize`.
245 lines
8.8 KiB
Rust
245 lines
8.8 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* 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/. */
|
|
|
|
//! Generic types for CSS values in SVG
|
|
|
|
use cssparser::Parser;
|
|
use parser::{Parse, ParserContext};
|
|
use std::fmt;
|
|
use style_traits::{ParseError, StyleParseErrorKind, ToCss};
|
|
use values::{Either, None_};
|
|
use values::computed::NumberOrPercentage;
|
|
use values::computed::length::LengthOrPercentage;
|
|
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
|
|
|
/// An SVG paint value
|
|
///
|
|
/// <https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint>
|
|
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq)]
|
|
#[derive(ToAnimatedValue, ToComputedValue, ToCss)]
|
|
pub struct SVGPaint<ColorType, UrlPaintServer> {
|
|
/// The paint source
|
|
pub kind: SVGPaintKind<ColorType, UrlPaintServer>,
|
|
/// The fallback color. It would be empty, the `none` keyword or <color>.
|
|
pub fallback: Option<Either<ColorType, None_>>,
|
|
}
|
|
|
|
/// An SVG paint value without the fallback
|
|
///
|
|
/// Whereas the spec only allows PaintServer
|
|
/// to have a fallback, Gecko lets the context
|
|
/// properties have a fallback as well.
|
|
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq)]
|
|
#[derive(ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
|
|
pub enum SVGPaintKind<ColorType, UrlPaintServer> {
|
|
/// `none`
|
|
#[animation(error)]
|
|
None,
|
|
/// `<color>`
|
|
Color(ColorType),
|
|
/// `url(...)`
|
|
#[animation(error)]
|
|
PaintServer(UrlPaintServer),
|
|
/// `context-fill`
|
|
ContextFill,
|
|
/// `context-stroke`
|
|
ContextStroke,
|
|
}
|
|
|
|
impl<ColorType, UrlPaintServer> SVGPaintKind<ColorType, UrlPaintServer> {
|
|
/// Parse a keyword value only
|
|
fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
|
try_match_ident_ignore_ascii_case! { input,
|
|
"none" => Ok(SVGPaintKind::None),
|
|
"context-fill" => Ok(SVGPaintKind::ContextFill),
|
|
"context-stroke" => Ok(SVGPaintKind::ContextStroke),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Parse SVGPaint's fallback.
|
|
/// fallback is keyword(none), Color or empty.
|
|
/// <https://svgwg.org/svg2-draft/painting.html#SpecifyingPaint>
|
|
fn parse_fallback<'i, 't, ColorType: Parse>(context: &ParserContext,
|
|
input: &mut Parser<'i, 't>)
|
|
-> Option<Either<ColorType, None_>> {
|
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
|
Some(Either::Second(None_))
|
|
} else {
|
|
if let Ok(color) = input.try(|i| ColorType::parse(context, i)) {
|
|
Some(Either::First(color))
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlPaintServer> {
|
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
|
if let Ok(url) = input.try(|i| UrlPaintServer::parse(context, i)) {
|
|
Ok(SVGPaint {
|
|
kind: SVGPaintKind::PaintServer(url),
|
|
fallback: parse_fallback(context, input),
|
|
})
|
|
} else if let Ok(kind) = input.try(SVGPaintKind::parse_ident) {
|
|
if let SVGPaintKind::None = kind {
|
|
Ok(SVGPaint {
|
|
kind: kind,
|
|
fallback: None,
|
|
})
|
|
} else {
|
|
Ok(SVGPaint {
|
|
kind: kind,
|
|
fallback: parse_fallback(context, input),
|
|
})
|
|
}
|
|
} else if let Ok(color) = input.try(|i| ColorType::parse(context, i)) {
|
|
Ok(SVGPaint {
|
|
kind: SVGPaintKind::Color(color),
|
|
fallback: None,
|
|
})
|
|
} else {
|
|
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A value of <length> | <percentage> | <number> for svg which allow unitless length.
|
|
/// <https://www.w3.org/TR/SVG11/painting.html#StrokeProperties>
|
|
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedValue)]
|
|
#[derive(ToAnimatedZero, ToComputedValue, ToCss)]
|
|
pub enum SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number> {
|
|
/// <length> | <percentage>
|
|
LengthOrPercentage(LengthOrPercentage),
|
|
/// <number>
|
|
Number(Number),
|
|
}
|
|
|
|
impl<L, N> ComputeSquaredDistance for SvgLengthOrPercentageOrNumber<L, N>
|
|
where
|
|
L: ComputeSquaredDistance + Copy + Into<NumberOrPercentage>,
|
|
N: ComputeSquaredDistance + Copy + Into<NumberOrPercentage>
|
|
{
|
|
#[inline]
|
|
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
|
match (self, other) {
|
|
(
|
|
&SvgLengthOrPercentageOrNumber::LengthOrPercentage(ref from),
|
|
&SvgLengthOrPercentageOrNumber::LengthOrPercentage(ref to)
|
|
) => {
|
|
from.compute_squared_distance(to)
|
|
},
|
|
(
|
|
&SvgLengthOrPercentageOrNumber::Number(ref from),
|
|
&SvgLengthOrPercentageOrNumber::Number(ref to)
|
|
) => {
|
|
from.compute_squared_distance(to)
|
|
},
|
|
(
|
|
&SvgLengthOrPercentageOrNumber::LengthOrPercentage(from),
|
|
&SvgLengthOrPercentageOrNumber::Number(to)
|
|
) => {
|
|
from.into().compute_squared_distance(&to.into())
|
|
},
|
|
(
|
|
&SvgLengthOrPercentageOrNumber::Number(from),
|
|
&SvgLengthOrPercentageOrNumber::LengthOrPercentage(to)
|
|
) => {
|
|
from.into().compute_squared_distance(&to.into())
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<LengthOrPercentageType, NumberType> SvgLengthOrPercentageOrNumber<LengthOrPercentageType, NumberType>
|
|
where LengthOrPercentage: From<LengthOrPercentageType>,
|
|
LengthOrPercentageType: Copy
|
|
{
|
|
/// return true if this struct has calc value.
|
|
pub fn has_calc(&self) -> bool {
|
|
match self {
|
|
&SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop) => {
|
|
match LengthOrPercentage::from(lop) {
|
|
LengthOrPercentage::Calc(_) => true,
|
|
_ => false,
|
|
}
|
|
},
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Parsing the SvgLengthOrPercentageOrNumber. At first, we need to parse number
|
|
/// since prevent converting to the length.
|
|
impl <LengthOrPercentageType: Parse, NumberType: Parse> Parse for
|
|
SvgLengthOrPercentageOrNumber<LengthOrPercentageType, NumberType> {
|
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
|
-> Result<Self, ParseError<'i>> {
|
|
if let Ok(num) = input.try(|i| NumberType::parse(context, i)) {
|
|
return Ok(SvgLengthOrPercentageOrNumber::Number(num));
|
|
}
|
|
|
|
if let Ok(lop) = input.try(|i| LengthOrPercentageType::parse(context, i)) {
|
|
return Ok(SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop));
|
|
}
|
|
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
|
}
|
|
}
|
|
|
|
/// An SVG length value supports `context-value` in addition to length.
|
|
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq)]
|
|
#[derive(ToAnimatedValue, ToAnimatedZero)]
|
|
#[derive(ToComputedValue, ToCss)]
|
|
pub enum SVGLength<LengthType> {
|
|
/// `<length> | <percentage> | <number>`
|
|
Length(LengthType),
|
|
/// `context-value`
|
|
ContextValue,
|
|
}
|
|
|
|
/// Generic value for stroke-dasharray.
|
|
#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, ToAnimatedValue,
|
|
ToComputedValue)]
|
|
pub enum SVGStrokeDashArray<LengthType> {
|
|
/// `[ <length> | <percentage> | <number> ]#`
|
|
Values(Vec<LengthType>),
|
|
/// `context-value`
|
|
ContextValue,
|
|
}
|
|
|
|
impl<LengthType> ToCss for SVGStrokeDashArray<LengthType> where LengthType: ToCss {
|
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
|
match self {
|
|
&SVGStrokeDashArray::Values(ref values) => {
|
|
let mut iter = values.iter();
|
|
if let Some(first) = iter.next() {
|
|
first.to_css(dest)?;
|
|
for item in iter {
|
|
dest.write_str(", ")?;
|
|
item.to_css(dest)?;
|
|
}
|
|
Ok(())
|
|
} else {
|
|
dest.write_str("none")
|
|
}
|
|
}
|
|
&SVGStrokeDashArray::ContextValue => {
|
|
dest.write_str("context-value")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// An SVG opacity value accepts `context-{fill,stroke}-opacity` in
|
|
/// addition to opacity value.
|
|
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf)]
|
|
#[derive(PartialEq, ToAnimatedZero, ToComputedValue, ToCss)]
|
|
pub enum SVGOpacity<OpacityType> {
|
|
/// `<opacity-value>`
|
|
Opacity(OpacityType),
|
|
/// `context-fill-opacity`
|
|
ContextFillOpacity,
|
|
/// `context-stroke-opacity`
|
|
ContextStrokeOpacity,
|
|
}
|