mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 20:30:41 +00:00
Bug 1798932 - Don't bother preserving authored colors for canvas. r=tlouw
Differential Revision: https://phabricator.services.mozilla.com/D161266
This commit is contained in:
parent
027638529a
commit
cfe3a0e68a
@ -5,6 +5,7 @@
|
||||
//! Specified color values.
|
||||
|
||||
use super::AllowQuirks;
|
||||
use crate::media_queries::Device;
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
use crate::values::computed::{Color as ComputedColor, Context, ToComputedValue};
|
||||
use crate::values::generics::color::{
|
||||
@ -24,10 +25,11 @@ use style_traits::{SpecifiedValueInfo, ToCss, ValueParseErrorKind};
|
||||
/// A specified color-mix().
|
||||
pub type ColorMix = GenericColorMix<Color, Percentage>;
|
||||
|
||||
impl Parse for ColorMix {
|
||||
impl ColorMix {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
preserve_authored: PreserveAuthored,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let enabled =
|
||||
context.chrome_rules_enabled() || static_prefs::pref!("layout.css.color-mix.enabled");
|
||||
@ -50,7 +52,7 @@ impl Parse for ColorMix {
|
||||
|
||||
let mut left_percentage = try_parse_percentage(input);
|
||||
|
||||
let left = Color::parse(context, input)?;
|
||||
let left = Color::parse_internal(context, input, preserve_authored)?;
|
||||
if left_percentage.is_none() {
|
||||
left_percentage = try_parse_percentage(input);
|
||||
}
|
||||
@ -431,17 +433,40 @@ impl<'a, 'b: 'a, 'i: 'a> ::cssparser::ColorComponentParser<'i> for ColorComponen
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether to preserve authored colors during parsing. That's useful only if we
|
||||
/// plan to serialize the color back.
|
||||
enum PreserveAuthored {
|
||||
No,
|
||||
Yes,
|
||||
}
|
||||
|
||||
impl Parse for Color {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
// Currently we only store authored value for color keywords,
|
||||
// because all browsers serialize those values as keywords for
|
||||
// specified value.
|
||||
let start = input.state();
|
||||
let authored = input.expect_ident_cloned().ok();
|
||||
input.reset(&start);
|
||||
Self::parse_internal(context, input, PreserveAuthored::Yes)
|
||||
}
|
||||
}
|
||||
|
||||
impl Color {
|
||||
fn parse_internal<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
preserve_authored: PreserveAuthored,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let authored = match preserve_authored {
|
||||
PreserveAuthored::No => None,
|
||||
PreserveAuthored::Yes => {
|
||||
// Currently we only store authored value for color keywords,
|
||||
// because all browsers serialize those values as keywords for
|
||||
// specified value.
|
||||
let start = input.state();
|
||||
let authored = input.expect_ident_cloned().ok();
|
||||
input.reset(&start);
|
||||
authored
|
||||
}
|
||||
};
|
||||
|
||||
let compontent_parser = ColorComponentParser(&*context);
|
||||
match input.try_parse(|i| CSSParserColor::parse_with(&compontent_parser, i)) {
|
||||
@ -460,7 +485,7 @@ impl Parse for Color {
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(mix) = input.try_parse(|i| ColorMix::parse(context, i)) {
|
||||
if let Ok(mix) = input.try_parse(|i| ColorMix::parse(context, i, preserve_authored)) {
|
||||
return Ok(Color::ColorMix(Box::new(mix)));
|
||||
}
|
||||
|
||||
@ -475,6 +500,58 @@ impl Parse for Color {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether a given color is valid for authors.
|
||||
pub fn is_valid(context: &ParserContext, input: &mut Parser) -> bool {
|
||||
input.parse_entirely(|input| Self::parse_internal(context, input, PreserveAuthored::No)).is_ok()
|
||||
}
|
||||
|
||||
/// Tries to parse a color and compute it with a given device.
|
||||
pub fn parse_and_compute(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
device: Option<&Device>,
|
||||
) -> Option<ComputedColor> {
|
||||
use crate::error_reporting::ContextualParseError;
|
||||
let start = input.position();
|
||||
let result = input.parse_entirely(|input| {
|
||||
Self::parse_internal(context, input, PreserveAuthored::No)
|
||||
});
|
||||
|
||||
let specified = match result {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
if !context.error_reporting_enabled() {
|
||||
return None;
|
||||
}
|
||||
// Ignore other kinds of errors that might be reported, such as
|
||||
// ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken),
|
||||
// since Gecko didn't use to report those to the error console.
|
||||
//
|
||||
// TODO(emilio): Revise whether we want to keep this at all, we
|
||||
// use this only for canvas, this warnings are disabled by
|
||||
// default and not available on OffscreenCanvas anyways...
|
||||
if let ParseErrorKind::Custom(StyleParseErrorKind::ValueError(..)) = e.kind {
|
||||
let location = e.location.clone();
|
||||
let error = ContextualParseError::UnsupportedValue(
|
||||
input.slice_from(start),
|
||||
e,
|
||||
);
|
||||
context.log_css_error(location, error);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
match device {
|
||||
Some(device) => {
|
||||
Context::for_media_query_evaluation(device, device.quirks_mode(), |context| {
|
||||
specified.to_computed_color(Some(&context))
|
||||
})
|
||||
},
|
||||
None => specified.to_computed_color(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for Color {
|
||||
|
@ -6,7 +6,7 @@ use super::error_reporter::ErrorReporter;
|
||||
use super::stylesheet_loader::{AsyncStylesheetParser, StylesheetLoader};
|
||||
use bincode::{deserialize, serialize};
|
||||
use cssparser::ToCss as ParserToCss;
|
||||
use cssparser::{ParseErrorKind, Parser, ParserInput, SourceLocation, UnicodeRange};
|
||||
use cssparser::{Parser, ParserInput, SourceLocation, UnicodeRange};
|
||||
use dom::{DocumentState, ElementState};
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use nsstring::{nsCString, nsString};
|
||||
@ -26,7 +26,7 @@ use style::counter_style;
|
||||
use style::data::{self, ElementStyles};
|
||||
use style::dom::{ShowSubtreeData, TDocument, TElement, TNode};
|
||||
use style::driver;
|
||||
use style::error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use style::error_reporting::ParseErrorReporter;
|
||||
use style::font_face::{self, FontFaceSourceFormat, FontFaceSourceListComponent, Source};
|
||||
use style::gecko::data::{GeckoStyleSheet, PerDocumentStyleData, PerDocumentStyleDataImpl};
|
||||
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
||||
@ -146,7 +146,7 @@ use style::values::generics::easing::BeforeFlag;
|
||||
use style::values::specified::gecko::IntersectionObserverRootMargin;
|
||||
use style::values::specified::source_size_list::SourceSizeList;
|
||||
use style::values::{specified, AtomIdent, CustomIdent, KeyframesName};
|
||||
use style_traits::{CssWriter, ParsingMode, StyleParseErrorKind, ToCss};
|
||||
use style_traits::{CssWriter, ParsingMode, ToCss};
|
||||
use to_shmem::SharedMemoryBuilder;
|
||||
|
||||
trait ClosureHelper {
|
||||
@ -6950,49 +6950,20 @@ pub unsafe extern "C" fn Servo_SelectorList_Drop(list: *mut RawServoSelectorList
|
||||
SelectorList::drop_ffi(list)
|
||||
}
|
||||
|
||||
fn parse_color(
|
||||
value: &str,
|
||||
error_reporter: Option<&dyn ParseErrorReporter>,
|
||||
) -> Result<specified::Color, ()> {
|
||||
let mut input = ParserInput::new(value);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let url_data = unsafe { dummy_url_data() };
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_IsValidCSSColor(value: &nsACString) -> bool {
|
||||
let mut input = ParserInput::new(value.as_str_unchecked());
|
||||
let mut input = Parser::new(&mut input);
|
||||
let context = ParserContext::new(
|
||||
Origin::Author,
|
||||
url_data,
|
||||
dummy_url_data(),
|
||||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
error_reporter,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
let start_position = parser.position();
|
||||
parser
|
||||
.parse_entirely(|i| specified::Color::parse(&context, i))
|
||||
.map_err(|err| {
|
||||
if error_reporter.is_some() {
|
||||
match err.kind {
|
||||
ParseErrorKind::Custom(StyleParseErrorKind::ValueError(..)) => {
|
||||
let location = err.location.clone();
|
||||
let error = ContextualParseError::UnsupportedValue(
|
||||
parser.slice_from(start_position),
|
||||
err,
|
||||
);
|
||||
context.log_css_error(location, error);
|
||||
},
|
||||
// Ignore other kinds of errors that might be reported, such as
|
||||
// ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken),
|
||||
// since Gecko doesn't report those to the error console.
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_IsValidCSSColor(value: &nsACString) -> bool {
|
||||
parse_color(value.as_str_unchecked(), None).is_ok()
|
||||
specified::Color::is_valid(&context, &mut input)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -7004,47 +6975,44 @@ pub unsafe extern "C" fn Servo_ComputeColor(
|
||||
was_current_color: *mut bool,
|
||||
loader: *mut Loader,
|
||||
) -> bool {
|
||||
use style::gecko;
|
||||
|
||||
let current_color = gecko::values::convert_nscolor_to_rgba(current_color);
|
||||
|
||||
let mut input = ParserInput::new(value.as_str_unchecked());
|
||||
let mut input = Parser::new(&mut input);
|
||||
let reporter = loader.as_mut().and_then(|loader| {
|
||||
// Make an ErrorReporter that will report errors as being "from DOM".
|
||||
ErrorReporter::new(ptr::null_mut(), loader, ptr::null_mut())
|
||||
});
|
||||
|
||||
let specified_color = match parse_color(
|
||||
value.as_str_unchecked(),
|
||||
reporter.as_ref().map(|r| r as &dyn ParseErrorReporter),
|
||||
) {
|
||||
Ok(c) => c,
|
||||
Err(..) => return false,
|
||||
};
|
||||
let context = ParserContext::new(
|
||||
Origin::Author,
|
||||
dummy_url_data(),
|
||||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
reporter.as_ref().map(|e| e as &dyn ParseErrorReporter),
|
||||
None,
|
||||
);
|
||||
|
||||
let computed_color = match raw_data {
|
||||
Some(raw_data) => {
|
||||
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
||||
let device = data.stylist.device();
|
||||
let quirks_mode = data.stylist.quirks_mode();
|
||||
Context::for_media_query_evaluation(device, quirks_mode, |context| {
|
||||
specified_color.to_computed_color(Some(&context))
|
||||
})
|
||||
let data;
|
||||
let device = match raw_data {
|
||||
Some(d) => {
|
||||
data = PerDocumentStyleData::from_ffi(d).borrow();
|
||||
Some(data.stylist.device())
|
||||
},
|
||||
None => specified_color.to_computed_color(None),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let computed_color = match computed_color {
|
||||
let computed = match specified::Color::parse_and_compute(&context, &mut input, device) {
|
||||
Some(c) => c,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
let current_color = style::gecko::values::convert_nscolor_to_rgba(current_color);
|
||||
if !was_current_color.is_null() {
|
||||
*was_current_color = computed_color.is_currentcolor();
|
||||
*was_current_color = computed.is_currentcolor();
|
||||
}
|
||||
|
||||
let rgba = computed_color.into_rgba(current_color);
|
||||
*result_color = gecko::values::convert_rgba_to_nscolor(&rgba);
|
||||
|
||||
let rgba = computed.into_rgba(current_color);
|
||||
*result_color = style::gecko::values::convert_rgba_to_nscolor(&rgba);
|
||||
true
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user