--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -93,35 +93,39 @@ impl Device {
unsafe impl Sync for Device {}
unsafe impl Send for Device {}
/// A expression for gecko contains a reference to the media feature, the value
/// the media query contained, and the range to evaluate.
#[derive(Debug, Clone)]
pub struct Expression {
feature: &'static nsMediaFeature,
- value: MediaExpressionValue,
+ value: Option<MediaExpressionValue>,
range: nsMediaExpression_Range
}
impl ToCss for Expression {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
dest.write_str("(")?;
match self.range {
nsMediaExpression_Range::eMin => dest.write_str("min-")?,
nsMediaExpression_Range::eMax => dest.write_str("max-")?,
nsMediaExpression_Range::eEqual => {},
}
- // NB: CSSStringWriter not needed, features are under control.
+
+ // NB: CSSStringWriter not needed, feature names are under control.
write!(dest, "{}", Atom::from(unsafe { *self.feature.mName }))?;
- dest.write_str(": ")?;
- self.value.to_css(dest)?;
+ if let Some(ref val) = self.value {
+ dest.write_str(": ")?;
+ val.to_css(dest)?;
+ }
+
dest.write_str(")")
}
}
/// A resolution.
#[derive(Debug, Clone)]
pub enum Resolution {
/// Dots per inch.
@@ -208,17 +212,16 @@ impl ToCss for MediaExpressionValue {
}
}
fn starts_with_ignore_ascii_case(string: &str, prefix: &str) -> bool {
string.len() > prefix.len() &&
string[0..prefix.len()].eq_ignore_ascii_case(prefix)
}
-#[allow(warnings)]
fn find_feature<F>(mut f: F) -> Option<&'static nsMediaFeature>
where F: FnMut(&'static nsMediaFeature) -> bool,
{
// FIXME(emilio): With build-time bindgen, we would be able to use
// structs::nsMediaFeatures_features. That would unfortunately break MSVC
// builds, or require one bindings file per platform.
//
// I'm not into any of those, so meanwhile let's use a FFI function.
@@ -233,36 +236,34 @@ fn find_feature<F>(mut f: F) -> Option<&
}
None
}
impl Expression {
/// Trivially construct a new expression.
fn new(feature: &'static nsMediaFeature,
- value: MediaExpressionValue,
+ value: Option<MediaExpressionValue>,
range: nsMediaExpression_Range) -> Self {
Expression {
feature: feature,
value: value,
range: range,
}
}
/// Parse a media expression of the form:
///
/// ```
/// (media-feature: media-value)
/// ```
- #[allow(warnings)]
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
try!(input.expect_parenthesis_block());
input.parse_nested_block(|input| {
let ident = try!(input.expect_ident());
- try!(input.expect_colon());
let mut flags = 0;
let mut feature_name = &*ident;
// TODO(emilio): this is under a pref in Gecko.
if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
feature_name = &feature_name[8..];
flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8;
@@ -289,16 +290,27 @@ impl Expression {
return Err(());
}
if range != nsMediaExpression_Range::eEqual &&
feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed {
return Err(());
}
+ // If there's no colon, this is a media query of the form
+ // '(<feature>)', that is, there's no value specified.
+ //
+ // FIXME(emilio): We need to check for range operators too here when
+ // we support them, see:
+ //
+ // https://drafts.csswg.org/mediaqueries/#mq-ranges
+ if input.try(|i| i.expect_colon()).is_err() {
+ return Ok(Expression::new(feature, None, range));
+ }
+
let value = match feature.mValueType {
nsMediaFeature_ValueType::eLength => {
MediaExpressionValue::Length(
specified::Length::parse_non_negative(input)?)
},
nsMediaFeature_ValueType::eInteger => {
let i = input.expect_integer()?;
if i < 0 {
@@ -331,16 +343,17 @@ impl Expression {
MediaExpressionValue::IntRatio(a as u32, b as u32)
}
nsMediaFeature_ValueType::eResolution => {
MediaExpressionValue::Resolution(Resolution::parse(input)?)
}
nsMediaFeature_ValueType::eEnumerated => {
let index = unsafe {
let _table = feature.mData.mKeywordTable.as_ref();
+ // TODO
0
};
MediaExpressionValue::Enumerated(index)
}
nsMediaFeature_ValueType::eIdent => {
MediaExpressionValue::Ident(input.expect_ident()?.into())
}
};