Move CSS Writing Modes properties behind a new command-line flag.

This commit is contained in:
Simon Sapin 2014-07-09 21:31:18 +01:00
parent 7f6bd1707e
commit bc2aa8430b
5 changed files with 275 additions and 167 deletions

View file

@ -97,6 +97,7 @@ pub extern "C" fn android_start(argc: int, argv: **u8) -> int {
#[cfg(not(test))] #[cfg(not(test))]
pub fn run(opts: opts::Opts) { pub fn run(opts: opts::Opts) {
::servo_util::opts::set_experimental_enabled(opts.enable_experimental);
RegisterBindings::RegisterProxyHandlers(); RegisterBindings::RegisterProxyHandlers();
let mut pool_config = green::PoolConfig::new(); let mut pool_config = green::PoolConfig::new();

View file

@ -35,7 +35,7 @@ def to_rust_ident(name):
return name return name
class Longhand(object): class Longhand(object):
def __init__(self, name, derived_from=None): def __init__(self, name, derived_from=None, experimental=False):
self.name = name self.name = name
self.ident = to_rust_ident(name) self.ident = to_rust_ident(name)
self.camel_case, _ = re.subn( self.camel_case, _ = re.subn(
@ -43,6 +43,7 @@ class Longhand(object):
lambda m: m.group(1).upper(), lambda m: m.group(1).upper(),
self.ident.strip("_").capitalize()) self.ident.strip("_").capitalize())
self.style_struct = THIS_STYLE_STRUCT self.style_struct = THIS_STYLE_STRUCT
self.experimental = experimental
if derived_from is None: if derived_from is None:
self.derived_from = None self.derived_from = None
else: else:
@ -94,12 +95,12 @@ pub mod longhands {
value value
} }
<%def name="raw_longhand(name, no_super=False, derived_from=None)"> <%def name="raw_longhand(name, no_super=False, derived_from=None, experimental=False)">
<% <%
if derived_from is not None: if derived_from is not None:
derived_from = derived_from.split() derived_from = derived_from.split()
property = Longhand(name, derived_from=derived_from) property = Longhand(name, derived_from=derived_from, experimental=experimental)
THIS_STYLE_STRUCT.longhands.append(property) THIS_STYLE_STRUCT.longhands.append(property)
LONGHANDS.append(property) LONGHANDS.append(property)
LONGHANDS_BY_NAME[name] = property LONGHANDS_BY_NAME[name] = property
@ -128,8 +129,9 @@ pub mod longhands {
} }
</%def> </%def>
<%def name="longhand(name, no_super=False, derived_from=None)"> <%def name="longhand(name, no_super=False, derived_from=None, experimental=False)">
<%self:raw_longhand name="${name}" derived_from="${derived_from}"> <%self:raw_longhand name="${name}" derived_from="${derived_from}"
experimental="${experimental}">
${caller.body()} ${caller.body()}
% if derived_from is None: % if derived_from is None:
pub fn parse_specified(_input: &[ComponentValue], _base_url: &Url) pub fn parse_specified(_input: &[ComponentValue], _base_url: &Url)
@ -140,8 +142,9 @@ pub mod longhands {
</%self:raw_longhand> </%self:raw_longhand>
</%def> </%def>
<%def name="single_component_value(name, derived_from=None)"> <%def name="single_component_value(name, derived_from=None, experimental=False)">
<%self:longhand name="${name}" derived_from="${derived_from}"> <%self:longhand name="${name}" derived_from="${derived_from}"
experimental="${experimental}">
${caller.body()} ${caller.body()}
pub fn parse(input: &[ComponentValue], base_url: &Url) -> Option<SpecifiedValue> { pub fn parse(input: &[ComponentValue], base_url: &Url) -> Option<SpecifiedValue> {
one_component_value(input).and_then(|c| from_component_value(c, base_url)) one_component_value(input).and_then(|c| from_component_value(c, base_url))
@ -149,8 +152,8 @@ pub mod longhands {
</%self:longhand> </%self:longhand>
</%def> </%def>
<%def name="single_keyword_computed(name, values)"> <%def name="single_keyword_computed(name, values, experimental=False)">
<%self:single_component_value name="${name}"> <%self:single_component_value name="${name}" experimental="${experimental}">
${caller.body()} ${caller.body()}
pub mod computed_value { pub mod computed_value {
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@ -179,9 +182,10 @@ pub mod longhands {
</%self:single_component_value> </%self:single_component_value>
</%def> </%def>
<%def name="single_keyword(name, values)"> <%def name="single_keyword(name, values, experimental=False)">
<%self:single_keyword_computed name="${name}" <%self:single_keyword_computed name="${name}"
values="${values}"> values="${values}"
experimental="${experimental}">
// The computed value is the same as the specified value. // The computed value is the same as the specified value.
pub use to_computed_value = super::computed_as_specified; pub use to_computed_value = super::computed_as_specified;
</%self:single_keyword_computed> </%self:single_keyword_computed>
@ -323,7 +327,7 @@ pub mod longhands {
${new_style_struct("InheritedBox", is_inherited=True)} ${new_style_struct("InheritedBox", is_inherited=True)}
${single_keyword("direction", "ltr rtl")} ${single_keyword("direction", "ltr rtl", experimental=True)}
// CSS 2.1, Section 10 - Visual formatting model details // CSS 2.1, Section 10 - Visual formatting model details
@ -1041,11 +1045,11 @@ pub mod longhands {
// http://dev.w3.org/csswg/css-writing-modes/ // http://dev.w3.org/csswg/css-writing-modes/
${switch_to_style_struct("InheritedBox")} ${switch_to_style_struct("InheritedBox")}
${single_keyword("writing-mode", "horizontal-tb vertical-rl vertical-lr")} ${single_keyword("writing-mode", "horizontal-tb vertical-rl vertical-lr", experimental=True)}
// FIXME(SimonSapin): Add 'mixed' and 'upright' (needs vertical text support) // FIXME(SimonSapin): Add 'mixed' and 'upright' (needs vertical text support)
// FIXME(SimonSapin): initial (first) value should be 'mixed', when that's implemented // FIXME(SimonSapin): initial (first) value should be 'mixed', when that's implemented
${single_keyword("text-orientation", "sideways sideways-left sideways-right")} ${single_keyword("text-orientation", "sideways sideways-left sideways-right", experimental=True)}
} }
@ -1436,6 +1440,10 @@ pub fn parse_property_declaration_list<I: Iterator<Node>>(input: I, base_url: &U
match PropertyDeclaration::parse(n.as_slice(), v.as_slice(), list, base_url, seen) { match PropertyDeclaration::parse(n.as_slice(), v.as_slice(), list, base_url, seen) {
UnknownProperty => log_css_error(l, format!( UnknownProperty => log_css_error(l, format!(
"Unsupported property: {}:{}", n, v.iter().to_css()).as_slice()), "Unsupported property: {}:{}", n, v.iter().to_css()).as_slice()),
ExperimentalProperty => log_css_error(l, format!(
"Experimental property, use `servo --enable_experimental` \
or `servo -e` to enable: {}:{}",
n, v.iter().to_css()).as_slice()),
InvalidValue => log_css_error(l, format!( InvalidValue => log_css_error(l, format!(
"Invalid value: {}:{}", n, v.iter().to_css()).as_slice()), "Invalid value: {}:{}", n, v.iter().to_css()).as_slice()),
ValidOrIgnoredDeclaration => (), ValidOrIgnoredDeclaration => (),
@ -1486,6 +1494,7 @@ pub enum PropertyDeclaration {
pub enum PropertyDeclarationParseResult { pub enum PropertyDeclarationParseResult {
UnknownProperty, UnknownProperty,
ExperimentalProperty,
InvalidValue, InvalidValue,
ValidOrIgnoredDeclaration, ValidOrIgnoredDeclaration,
} }
@ -1502,6 +1511,11 @@ impl PropertyDeclaration {
% for property in LONGHANDS: % for property in LONGHANDS:
% if property.derived_from is None: % if property.derived_from is None:
"${property.name}" => { "${property.name}" => {
% if property.experimental:
if !::servo_util::opts::experimental_enabled() {
return ExperimentalProperty
}
% endif
if seen.get_${property.ident}() { if seen.get_${property.ident}() {
return ValidOrIgnoredDeclaration return ValidOrIgnoredDeclaration
} }

View file

@ -67,7 +67,7 @@ pub enum PagePx {}
// See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info. // See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info.
// //
// FIXME: Implement Au using Length and ScaleFactor instead of a custom type. // FIXME: Implement Au using Length and ScaleFactor instead of a custom type.
#[deriving(Clone, PartialEq, PartialOrd, Zero)] #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Zero)]
pub struct Au(pub i32); pub struct Au(pub i32);
impl Default for Au { impl Default for Au {

View file

@ -5,6 +5,7 @@
/// Geometry in flow-relative space. /// Geometry in flow-relative space.
use geom::{Size2D, Point2D, SideOffsets2D, Rect}; use geom::{Size2D, Point2D, SideOffsets2D, Rect};
use std::cmp::{min, max};
use std::fmt::{Show, Formatter, FormatError}; use std::fmt::{Show, Formatter, FormatError};
use std::num::Zero; use std::num::Zero;
@ -130,15 +131,15 @@ impl Show for DebugWritingMode {
/// A 2D size in flow-relative dimensions /// A 2D size in flow-relative dimensions
#[deriving(PartialEq, Eq, Clone)] #[deriving(PartialEq, Eq, Clone)]
pub struct LogicalSize<T> { pub struct LogicalSize<T> {
pub isize: T, // inline-size (a.k.a. logical width) pub inline: T, // inline-size, a.k.a. logical width, a.k.a. measure
pub bsize: T, // block-size (a.k.a. logical height) pub block: T, // block-size, a.k.a. logical height, a.k.a. extent
debug_writing_mode: DebugWritingMode, debug_writing_mode: DebugWritingMode,
} }
impl<T: Show> Show for LogicalSize<T> { impl<T: Show> Show for LogicalSize<T> {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> { fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> {
write!(formatter, "LogicalSize[{}, {}, {}]", write!(formatter, "LogicalSize[{}, {}, {}]",
self.debug_writing_mode, self.isize, self.bsize) self.debug_writing_mode, self.inline, self.block)
} }
} }
@ -147,24 +148,24 @@ impl<T: Zero> LogicalSize<T> {
#[inline] #[inline]
pub fn zero(mode: WritingMode) -> LogicalSize<T> { pub fn zero(mode: WritingMode) -> LogicalSize<T> {
LogicalSize { LogicalSize {
isize: Zero::zero(), inline: Zero::zero(),
bsize: Zero::zero(), block: Zero::zero(),
debug_writing_mode: DebugWritingMode::new(mode), debug_writing_mode: DebugWritingMode::new(mode),
} }
} }
#[inline] #[inline]
pub fn is_zero(&self) -> bool { pub fn is_zero(&self) -> bool {
self.isize.is_zero() && self.bsize.is_zero() self.inline.is_zero() && self.block.is_zero()
} }
} }
impl<T: Copy> LogicalSize<T> { impl<T: Copy> LogicalSize<T> {
#[inline] #[inline]
pub fn new(mode: WritingMode, isize: T, bsize: T) -> LogicalSize<T> { pub fn new(mode: WritingMode, inline: T, block: T) -> LogicalSize<T> {
LogicalSize { LogicalSize {
isize: isize, inline: inline,
bsize: bsize, block: block,
debug_writing_mode: DebugWritingMode::new(mode), debug_writing_mode: DebugWritingMode::new(mode),
} }
} }
@ -182,9 +183,9 @@ impl<T: Copy> LogicalSize<T> {
pub fn width(&self, mode: WritingMode) -> T { pub fn width(&self, mode: WritingMode) -> T {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
self.bsize self.block
} else { } else {
self.isize self.inline
} }
} }
@ -192,9 +193,9 @@ impl<T: Copy> LogicalSize<T> {
pub fn set_width(&mut self, mode: WritingMode, width: T) { pub fn set_width(&mut self, mode: WritingMode, width: T) {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
self.bsize = width self.block = width
} else { } else {
self.isize = width self.inline = width
} }
} }
@ -202,9 +203,9 @@ impl<T: Copy> LogicalSize<T> {
pub fn height(&self, mode: WritingMode) -> T { pub fn height(&self, mode: WritingMode) -> T {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
self.isize self.inline
} else { } else {
self.bsize self.block
} }
} }
@ -212,9 +213,9 @@ impl<T: Copy> LogicalSize<T> {
pub fn set_height(&mut self, mode: WritingMode, height: T) { pub fn set_height(&mut self, mode: WritingMode, height: T) {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
self.isize = height self.inline = height
} else { } else {
self.bsize = height self.block = height
} }
} }
@ -222,9 +223,9 @@ impl<T: Copy> LogicalSize<T> {
pub fn to_physical(&self, mode: WritingMode) -> Size2D<T> { pub fn to_physical(&self, mode: WritingMode) -> Size2D<T> {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
Size2D { width: self.bsize, height: self.isize } Size2D { width: self.block, height: self.inline }
} else { } else {
Size2D { width: self.isize, height: self.bsize } Size2D { width: self.inline, height: self.block }
} }
} }
@ -245,8 +246,8 @@ impl<T: Add<T, T>> Add<LogicalSize<T>, LogicalSize<T>> for LogicalSize<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode); self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalSize { LogicalSize {
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,
isize: self.isize + other.isize, inline: self.inline + other.inline,
bsize: self.bsize + other.bsize, block: self.block + other.block,
} }
} }
} }
@ -257,8 +258,8 @@ impl<T: Sub<T, T>> Sub<LogicalSize<T>, LogicalSize<T>> for LogicalSize<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode); self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalSize { LogicalSize {
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,
isize: self.isize - other.isize, inline: self.inline - other.inline,
bsize: self.bsize - other.bsize, block: self.block - other.block,
} }
} }
} }
@ -395,14 +396,28 @@ impl<T: Copy + Sub<T, T>> LogicalPoint<T> {
} }
} }
impl<T: Add<T,T>> LogicalPoint<T> {
/// This doesnt really makes sense,
/// but happens when dealing with mutliple origins.
#[inline]
pub fn add_point(&self, other: &LogicalPoint<T>) -> LogicalPoint<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalPoint {
debug_writing_mode: self.debug_writing_mode,
i: self.i + other.i,
b: self.b + other.b,
}
}
}
impl<T: Add<T,T>> Add<LogicalSize<T>, LogicalPoint<T>> for LogicalPoint<T> { impl<T: Add<T,T>> Add<LogicalSize<T>, LogicalPoint<T>> for LogicalPoint<T> {
#[inline] #[inline]
fn add(&self, other: &LogicalSize<T>) -> LogicalPoint<T> { fn add(&self, other: &LogicalSize<T>) -> LogicalPoint<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode); self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalPoint { LogicalPoint {
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,
i: self.i + other.isize, i: self.i + other.inline,
b: self.b + other.bsize, b: self.b + other.block,
} }
} }
} }
@ -413,8 +428,8 @@ impl<T: Sub<T,T>> Sub<LogicalSize<T>, LogicalPoint<T>> for LogicalPoint<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode); self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalPoint { LogicalPoint {
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,
i: self.i - other.isize, i: self.i - other.inline,
b: self.b - other.bsize, b: self.b - other.block,
} }
} }
} }
@ -426,17 +441,20 @@ impl<T: Sub<T,T>> Sub<LogicalSize<T>, LogicalPoint<T>> for LogicalPoint<T> {
/// A positive "margin" can be added to a rectangle to obtain a bigger rectangle. /// A positive "margin" can be added to a rectangle to obtain a bigger rectangle.
#[deriving(PartialEq, Eq, Clone)] #[deriving(PartialEq, Eq, Clone)]
pub struct LogicalMargin<T> { pub struct LogicalMargin<T> {
pub bstart: T, pub block_start: T,
pub iend: T, pub inline_end: T,
pub bend: T, pub block_end: T,
pub istart: T, pub inline_start: T,
debug_writing_mode: DebugWritingMode, debug_writing_mode: DebugWritingMode,
} }
impl<T: Show> Show for LogicalMargin<T> { impl<T: Show> Show for LogicalMargin<T> {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> { fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> {
write!(formatter, "LogicalMargin[{}, bstart: {}, iend: {}, bend: {}, istart: {}]", write!(formatter,
self.debug_writing_mode, self.bstart, self.iend, self.bend, self.istart) "LogicalMargin[{}, block_start: {}, inline_end: {}, \
block_end: {}, inline_start: {}]",
self.debug_writing_mode, self.block_start,
self.inline_end, self.block_end, self.inline_start)
} }
} }
@ -444,77 +462,83 @@ impl<T: Zero> LogicalMargin<T> {
#[inline] #[inline]
pub fn zero(mode: WritingMode) -> LogicalMargin<T> { pub fn zero(mode: WritingMode) -> LogicalMargin<T> {
LogicalMargin { LogicalMargin {
bstart: Zero::zero(), block_start: Zero::zero(),
iend: Zero::zero(), inline_end: Zero::zero(),
bend: Zero::zero(), block_end: Zero::zero(),
istart: Zero::zero(), inline_start: Zero::zero(),
debug_writing_mode: DebugWritingMode::new(mode), debug_writing_mode: DebugWritingMode::new(mode),
} }
} }
#[inline] #[inline]
pub fn is_zero(&self) -> bool { pub fn is_zero(&self) -> bool {
self.bstart.is_zero() && self.block_start.is_zero() &&
self.iend.is_zero() && self.inline_end.is_zero() &&
self.bend.is_zero() && self.block_end.is_zero() &&
self.istart.is_zero() self.inline_start.is_zero()
} }
} }
impl<T: Copy> LogicalMargin<T> { impl<T: Copy> LogicalMargin<T> {
#[inline] #[inline]
pub fn new(mode: WritingMode, bstart: T, iend: T, bend: T, istart: T) -> LogicalMargin<T> { pub fn new(mode: WritingMode, block_start: T, inline_end: T, block_end: T, inline_start: T)
-> LogicalMargin<T> {
LogicalMargin { LogicalMargin {
bstart: bstart, block_start: block_start,
iend: iend, inline_end: inline_end,
bend: bend, block_end: block_end,
istart: istart, inline_start: inline_start,
debug_writing_mode: DebugWritingMode::new(mode), debug_writing_mode: DebugWritingMode::new(mode),
} }
} }
#[inline]
pub fn new_all_same(mode: WritingMode, value: T) -> LogicalMargin<T> {
LogicalMargin::new(mode, value, value, value, value)
}
#[inline] #[inline]
pub fn from_physical(mode: WritingMode, offsets: SideOffsets2D<T>) -> LogicalMargin<T> { pub fn from_physical(mode: WritingMode, offsets: SideOffsets2D<T>) -> LogicalMargin<T> {
let bstart; let block_start;
let iend; let inline_end;
let bend; let block_end;
let istart; let inline_start;
if mode.is_vertical() { if mode.is_vertical() {
if mode.is_vertical_lr() { if mode.is_vertical_lr() {
bstart = offsets.left; block_start = offsets.left;
bend = offsets.right; block_end = offsets.right;
} else { } else {
bstart = offsets.right; block_start = offsets.right;
bend = offsets.left; block_end = offsets.left;
} }
if mode.is_inline_tb() { if mode.is_inline_tb() {
istart = offsets.top; inline_start = offsets.top;
iend = offsets.bottom; inline_end = offsets.bottom;
} else { } else {
istart = offsets.bottom; inline_start = offsets.bottom;
iend = offsets.top; inline_end = offsets.top;
} }
} else { } else {
bstart = offsets.top; block_start = offsets.top;
bend = offsets.bottom; block_end = offsets.bottom;
if mode.is_bidi_ltr() { if mode.is_bidi_ltr() {
istart = offsets.left; inline_start = offsets.left;
iend = offsets.right; inline_end = offsets.right;
} else { } else {
istart = offsets.right; inline_start = offsets.right;
iend = offsets.left; inline_end = offsets.left;
} }
} }
LogicalMargin::new(mode, bstart, iend, bend, istart) LogicalMargin::new(mode, block_start, inline_end, block_end, inline_start)
} }
#[inline] #[inline]
pub fn top(&self, mode: WritingMode) -> T { pub fn top(&self, mode: WritingMode) -> T {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
if mode.is_inline_tb() { self.istart } else { self.iend } if mode.is_inline_tb() { self.inline_start } else { self.inline_end }
} else { } else {
self.bstart self.block_start
} }
} }
@ -522,9 +546,9 @@ impl<T: Copy> LogicalMargin<T> {
pub fn set_top(&mut self, mode: WritingMode, top: T) { pub fn set_top(&mut self, mode: WritingMode, top: T) {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
if mode.is_inline_tb() { self.istart = top } else { self.iend = top } if mode.is_inline_tb() { self.inline_start = top } else { self.inline_end = top }
} else { } else {
self.bstart = top self.block_start = top
} }
} }
@ -532,9 +556,9 @@ impl<T: Copy> LogicalMargin<T> {
pub fn right(&self, mode: WritingMode) -> T { pub fn right(&self, mode: WritingMode) -> T {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
if mode.is_vertical_lr() { self.bend } else { self.bstart } if mode.is_vertical_lr() { self.block_end } else { self.block_start }
} else { } else {
if mode.is_bidi_ltr() { self.iend } else { self.istart } if mode.is_bidi_ltr() { self.inline_end } else { self.inline_start }
} }
} }
@ -542,9 +566,9 @@ impl<T: Copy> LogicalMargin<T> {
pub fn set_right(&mut self, mode: WritingMode, right: T) { pub fn set_right(&mut self, mode: WritingMode, right: T) {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
if mode.is_vertical_lr() { self.bend = right } else { self.bstart = right } if mode.is_vertical_lr() { self.block_end = right } else { self.block_start = right }
} else { } else {
if mode.is_bidi_ltr() { self.iend = right } else { self.istart = right } if mode.is_bidi_ltr() { self.inline_end = right } else { self.inline_start = right }
} }
} }
@ -552,9 +576,9 @@ impl<T: Copy> LogicalMargin<T> {
pub fn bottom(&self, mode: WritingMode) -> T { pub fn bottom(&self, mode: WritingMode) -> T {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
if mode.is_inline_tb() { self.iend } else { self.istart } if mode.is_inline_tb() { self.inline_end } else { self.inline_start }
} else { } else {
self.bend self.block_end
} }
} }
@ -562,9 +586,9 @@ impl<T: Copy> LogicalMargin<T> {
pub fn set_bottom(&mut self, mode: WritingMode, bottom: T) { pub fn set_bottom(&mut self, mode: WritingMode, bottom: T) {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
if mode.is_inline_tb() { self.iend = bottom } else { self.istart = bottom } if mode.is_inline_tb() { self.inline_end = bottom } else { self.inline_start = bottom }
} else { } else {
self.bend = bottom self.block_end = bottom
} }
} }
@ -572,9 +596,9 @@ impl<T: Copy> LogicalMargin<T> {
pub fn left(&self, mode: WritingMode) -> T { pub fn left(&self, mode: WritingMode) -> T {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
if mode.is_vertical_lr() { self.bstart } else { self.bend } if mode.is_vertical_lr() { self.block_start } else { self.block_end }
} else { } else {
if mode.is_bidi_ltr() { self.istart } else { self.iend } if mode.is_bidi_ltr() { self.inline_start } else { self.inline_end }
} }
} }
@ -582,9 +606,9 @@ impl<T: Copy> LogicalMargin<T> {
pub fn set_left(&mut self, mode: WritingMode, left: T) { pub fn set_left(&mut self, mode: WritingMode, left: T) {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
if mode.is_vertical_lr() { self.bstart = left } else { self.bend = left } if mode.is_vertical_lr() { self.block_start = left } else { self.block_end = left }
} else { } else {
if mode.is_bidi_ltr() { self.istart = left } else { self.iend = left } if mode.is_bidi_ltr() { self.inline_start = left } else { self.inline_end = left }
} }
} }
@ -597,28 +621,28 @@ impl<T: Copy> LogicalMargin<T> {
let left; let left;
if mode.is_vertical() { if mode.is_vertical() {
if mode.is_vertical_lr() { if mode.is_vertical_lr() {
left = self.bstart; left = self.block_start;
right = self.bend; right = self.block_end;
} else { } else {
right = self.bstart; right = self.block_start;
left = self.bend; left = self.block_end;
} }
if mode.is_inline_tb() { if mode.is_inline_tb() {
top = self.istart; top = self.inline_start;
bottom = self.iend; bottom = self.inline_end;
} else { } else {
bottom = self.istart; bottom = self.inline_start;
top = self.iend; top = self.inline_end;
} }
} else { } else {
top = self.bstart; top = self.block_start;
bottom = self.bend; bottom = self.block_end;
if mode.is_bidi_ltr() { if mode.is_bidi_ltr() {
left = self.istart; left = self.inline_start;
right = self.iend; right = self.inline_end;
} else { } else {
right = self.istart; right = self.inline_start;
left = self.iend; left = self.inline_end;
} }
} }
SideOffsets2D::new(top, right, bottom, left) SideOffsets2D::new(top, right, bottom, left)
@ -637,22 +661,22 @@ impl<T: Copy> LogicalMargin<T> {
impl<T: Add<T, T>> LogicalMargin<T> { impl<T: Add<T, T>> LogicalMargin<T> {
#[inline] #[inline]
pub fn istart_end(&self) -> T { pub fn inline_start_end(&self) -> T {
self.istart + self.iend self.inline_start + self.inline_end
} }
#[inline] #[inline]
pub fn bstart_end(&self) -> T { pub fn block_start_end(&self) -> T {
self.bstart + self.bend self.block_start + self.block_end
} }
#[inline] #[inline]
pub fn top_bottom(&self, mode: WritingMode) -> T { pub fn top_bottom(&self, mode: WritingMode) -> T {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
self.istart_end() self.inline_start_end()
} else { } else {
self.bstart_end() self.block_start_end()
} }
} }
@ -660,9 +684,9 @@ impl<T: Add<T, T>> LogicalMargin<T> {
pub fn left_right(&self, mode: WritingMode) -> T { pub fn left_right(&self, mode: WritingMode) -> T {
self.debug_writing_mode.check(mode); self.debug_writing_mode.check(mode);
if mode.is_vertical() { if mode.is_vertical() {
self.bstart_end() self.block_start_end()
} else { } else {
self.istart_end() self.inline_start_end()
} }
} }
} }
@ -673,10 +697,10 @@ impl<T: Add<T, T>> Add<LogicalMargin<T>, LogicalMargin<T>> for LogicalMargin<T>
self.debug_writing_mode.check_debug(other.debug_writing_mode); self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalMargin { LogicalMargin {
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,
bstart: self.bstart + other.bstart, block_start: self.block_start + other.block_start,
iend: self.iend + other.iend, inline_end: self.inline_end + other.inline_end,
bend: self.bend + other.bend, block_end: self.block_end + other.block_end,
istart: self.istart + other.istart, inline_start: self.inline_start + other.inline_start,
} }
} }
} }
@ -687,10 +711,10 @@ impl<T: Sub<T, T>> Sub<LogicalMargin<T>, LogicalMargin<T>> for LogicalMargin<T>
self.debug_writing_mode.check_debug(other.debug_writing_mode); self.debug_writing_mode.check_debug(other.debug_writing_mode);
LogicalMargin { LogicalMargin {
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,
bstart: self.bstart - other.bstart, block_start: self.block_start - other.block_start,
iend: self.iend - other.iend, inline_end: self.inline_end - other.inline_end,
bend: self.bend - other.bend, block_end: self.block_end - other.block_end,
istart: self.istart - other.istart, inline_start: self.inline_start - other.inline_start,
} }
} }
} }
@ -706,9 +730,11 @@ pub struct LogicalRect<T> {
impl<T: Show> Show for LogicalRect<T> { impl<T: Show> Show for LogicalRect<T> {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> { fn fmt(&self, formatter: &mut Formatter) -> Result<(), FormatError> {
write!(formatter, "LogicalRect[{}, istart: {}, bstart: {}, isize: {}, bsize: {}]", write!(formatter,
"LogicalRect[{}, inline_start: {}, block_start: {}, \
inline: {}, block: {}]",
self.debug_writing_mode, self.start.i, self.start.b, self.debug_writing_mode, self.start.i, self.start.b,
self.size.isize, self.size.bsize) self.size.inline, self.size.block)
} }
} }
@ -730,10 +756,23 @@ impl<T: Zero> LogicalRect<T> {
impl<T: Copy> LogicalRect<T> { impl<T: Copy> LogicalRect<T> {
#[inline] #[inline]
pub fn new(mode: WritingMode, istart: T, bstart: T, isize: T, bsize: T) -> LogicalRect<T> { pub fn new(mode: WritingMode, inline_start: T, block_start: T, inline: T, block: T)
-> LogicalRect<T> {
LogicalRect { LogicalRect {
start: LogicalPoint::new(mode, istart, bstart), start: LogicalPoint::new(mode, inline_start, block_start),
size: LogicalSize::new(mode, isize, bsize), size: LogicalSize::new(mode, inline, block),
debug_writing_mode: DebugWritingMode::new(mode),
}
}
#[inline]
pub fn from_point_size(mode: WritingMode, start: LogicalPoint<T>, size: LogicalSize<T>)
-> LogicalRect<T> {
start.debug_writing_mode.check(mode);
size.debug_writing_mode.check(mode);
LogicalRect {
start: start,
size: size,
debug_writing_mode: DebugWritingMode::new(mode), debug_writing_mode: DebugWritingMode::new(mode),
} }
} }
@ -743,48 +782,48 @@ impl<T: Copy + Add<T, T> + Sub<T, T>> LogicalRect<T> {
#[inline] #[inline]
pub fn from_physical(mode: WritingMode, rect: Rect<T>, container_size: Size2D<T>) pub fn from_physical(mode: WritingMode, rect: Rect<T>, container_size: Size2D<T>)
-> LogicalRect<T> { -> LogicalRect<T> {
let istart; let inline_start;
let bstart; let block_start;
let isize; let inline;
let bsize; let block;
if mode.is_vertical() { if mode.is_vertical() {
isize = rect.size.height; inline = rect.size.height;
bsize = rect.size.width; block = rect.size.width;
if mode.is_vertical_lr() { if mode.is_vertical_lr() {
bstart = rect.origin.x; block_start = rect.origin.x;
} else { } else {
bstart = container_size.width - (rect.origin.x + rect.size.width); block_start = container_size.width - (rect.origin.x + rect.size.width);
} }
if mode.is_inline_tb() { if mode.is_inline_tb() {
istart = rect.origin.y; inline_start = rect.origin.y;
} else { } else {
istart = container_size.height - (rect.origin.y + rect.size.height); inline_start = container_size.height - (rect.origin.y + rect.size.height);
} }
} else { } else {
isize = rect.size.width; inline = rect.size.width;
bsize = rect.size.height; block = rect.size.height;
bstart = rect.origin.y; block_start = rect.origin.y;
if mode.is_bidi_ltr() { if mode.is_bidi_ltr() {
istart = rect.origin.x; inline_start = rect.origin.x;
} else { } else {
istart = container_size.width - (rect.origin.x + rect.size.width); inline_start = container_size.width - (rect.origin.x + rect.size.width);
} }
} }
LogicalRect { LogicalRect {
start: LogicalPoint::new(mode, istart, bstart), start: LogicalPoint::new(mode, inline_start, block_start),
size: LogicalSize::new(mode, isize, bsize), size: LogicalSize::new(mode, inline, block),
debug_writing_mode: DebugWritingMode::new(mode), debug_writing_mode: DebugWritingMode::new(mode),
} }
} }
#[inline] #[inline]
pub fn iend(&self) -> T { pub fn inline_end(&self) -> T {
self.start.i + self.size.isize self.start.i + self.size.inline
} }
#[inline] #[inline]
pub fn bend(&self) -> T { pub fn block_end(&self) -> T {
self.start.b + self.size.bsize self.start.b + self.size.block
} }
#[inline] #[inline]
@ -795,26 +834,26 @@ impl<T: Copy + Add<T, T> + Sub<T, T>> LogicalRect<T> {
let width; let width;
let height; let height;
if mode.is_vertical() { if mode.is_vertical() {
width = self.size.bsize; width = self.size.block;
height = self.size.isize; height = self.size.inline;
if mode.is_vertical_lr() { if mode.is_vertical_lr() {
x = self.start.b; x = self.start.b;
} else { } else {
x = container_size.width - self.bend(); x = container_size.width - self.block_end();
} }
if mode.is_inline_tb() { if mode.is_inline_tb() {
y = self.start.i; y = self.start.i;
} else { } else {
y = container_size.height - self.iend(); y = container_size.height - self.inline_end();
} }
} else { } else {
width = self.size.isize; width = self.size.inline;
height = self.size.bsize; height = self.size.block;
y = self.start.b; y = self.start.b;
if mode.is_bidi_ltr() { if mode.is_bidi_ltr() {
x = self.start.i; x = self.start.i;
} else { } else {
x = container_size.width - self.iend(); x = container_size.width - self.inline_end();
} }
} }
Rect { Rect {
@ -834,6 +873,41 @@ impl<T: Copy + Add<T, T> + Sub<T, T>> LogicalRect<T> {
mode_to, self.to_physical(mode_from, container_size), container_size) mode_to, self.to_physical(mode_from, container_size), container_size)
} }
} }
pub fn translate(&self, offset: &LogicalPoint<T>) -> LogicalRect<T> {
LogicalRect {
start: self.start + LogicalSize {
inline: offset.i,
block: offset.b,
debug_writing_mode: offset.debug_writing_mode,
},
size: self.size,
debug_writing_mode: self.debug_writing_mode,
}
}
}
impl<T: Copy + Ord + Add<T, T> + Sub<T, T>> LogicalRect<T> {
#[inline]
pub fn union(&self, other: &LogicalRect<T>) -> LogicalRect<T> {
self.debug_writing_mode.check_debug(other.debug_writing_mode);
let inline_start = min(self.start.i, other.start.i);
let block_start = min(self.start.b, other.start.b);
LogicalRect {
start: LogicalPoint {
i: inline_start,
b: block_start,
debug_writing_mode: self.debug_writing_mode,
},
size: LogicalSize {
inline: max(self.inline_end(), other.inline_end()) - inline_start,
block: max(self.block_end(), other.block_end()) - block_start,
debug_writing_mode: self.debug_writing_mode,
},
debug_writing_mode: self.debug_writing_mode,
}
}
} }
impl<T: Add<T, T> + Sub<T, T>> Add<LogicalMargin<T>, LogicalRect<T>> for LogicalRect<T> { impl<T: Add<T, T> + Sub<T, T>> Add<LogicalMargin<T>, LogicalRect<T>> for LogicalRect<T> {
@ -844,13 +918,13 @@ impl<T: Add<T, T> + Sub<T, T>> Add<LogicalMargin<T>, LogicalRect<T>> for Logical
start: LogicalPoint { start: LogicalPoint {
// Growing a rectangle on the start side means pushing its // Growing a rectangle on the start side means pushing its
// start point on the negative direction. // start point on the negative direction.
i: self.start.i - other.istart, i: self.start.i - other.inline_start,
b: self.start.b - other.bstart, b: self.start.b - other.block_start,
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,
}, },
size: LogicalSize { size: LogicalSize {
isize: self.size.isize + other.istart_end(), inline: self.size.inline + other.inline_start_end(),
bsize: self.size.bsize + other.bstart_end(), block: self.size.block + other.block_start_end(),
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,
}, },
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,
@ -867,13 +941,13 @@ impl<T: Add<T, T> + Sub<T, T>> Sub<LogicalMargin<T>, LogicalRect<T>> for Logical
start: LogicalPoint { start: LogicalPoint {
// Shrinking a rectangle on the start side means pushing its // Shrinking a rectangle on the start side means pushing its
// start point on the positive direction. // start point on the positive direction.
i: self.start.i + other.istart, i: self.start.i + other.inline_start,
b: self.start.b + other.bstart, b: self.start.b + other.block_start,
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,
}, },
size: LogicalSize { size: LogicalSize {
isize: self.size.isize - other.istart_end(), inline: self.size.inline - other.inline_start_end(),
bsize: self.size.bsize - other.bstart_end(), block: self.size.block - other.block_start_end(),
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,
}, },
debug_writing_mode: self.debug_writing_mode, debug_writing_mode: self.debug_writing_mode,

View file

@ -49,6 +49,9 @@ pub struct Opts {
/// and cause it to produce output on that interval (`-m`). /// and cause it to produce output on that interval (`-m`).
pub memory_profiler_period: Option<f64>, pub memory_profiler_period: Option<f64>,
/// Enable experimental web features (`-e`).
pub enable_experimental: bool,
/// The number of threads to use for layout (`-y`). Defaults to 1, which results in a recursive /// The number of threads to use for layout (`-y`). Defaults to 1, which results in a recursive
/// sequential algorithm. /// sequential algorithm.
pub layout_threads: uint, pub layout_threads: uint,
@ -87,6 +90,7 @@ pub fn from_cmdline_args(args: &[String]) -> Option<Opts> {
getopts::optopt("r", "rendering", "Rendering backend", "direct2d|core-graphics|core-graphics-accelerated|cairo|skia."), getopts::optopt("r", "rendering", "Rendering backend", "direct2d|core-graphics|core-graphics-accelerated|cairo|skia."),
getopts::optopt("s", "size", "Size of tiles", "512"), getopts::optopt("s", "size", "Size of tiles", "512"),
getopts::optopt("", "device-pixel-ratio", "Device pixels per px", ""), getopts::optopt("", "device-pixel-ratio", "Device pixels per px", ""),
getopts::optflag("e", "experimental", "Enable experimental web features"),
getopts::optopt("t", "threads", "Number of render threads", "1"), getopts::optopt("t", "threads", "Number of render threads", "1"),
getopts::optflagopt("p", "profile", "Profiler flag and output interval", "10"), getopts::optflagopt("p", "profile", "Profiler flag and output interval", "10"),
getopts::optflagopt("m", "memory-profile", "Memory profiler flag and output interval", "10"), getopts::optflagopt("m", "memory-profile", "Memory profiler flag and output interval", "10"),
@ -176,6 +180,7 @@ pub fn from_cmdline_args(args: &[String]) -> Option<Opts> {
device_pixels_per_px: device_pixels_per_px, device_pixels_per_px: device_pixels_per_px,
time_profiler_period: time_profiler_period, time_profiler_period: time_profiler_period,
memory_profiler_period: memory_profiler_period, memory_profiler_period: memory_profiler_period,
enable_experimental: opt_match.opt_present("e"),
layout_threads: layout_threads, layout_threads: layout_threads,
exit_after_load: opt_match.opt_present("x"), exit_after_load: opt_match.opt_present("x"),
output_file: opt_match.opt_str("o"), output_file: opt_match.opt_str("o"),
@ -184,3 +189,17 @@ pub fn from_cmdline_args(args: &[String]) -> Option<Opts> {
bubble_widths_separately: opt_match.opt_present("b"), bubble_widths_separately: opt_match.opt_present("b"),
}) })
} }
static mut EXPERIMENTAL_ENABLED: bool = false;
pub fn set_experimental_enabled(new_value: bool) {
unsafe {
EXPERIMENTAL_ENABLED = new_value;
}
}
pub fn experimental_enabled() -> bool {
unsafe {
EXPERIMENTAL_ENABLED
}
}