Redo representation of CSS values, and many other related things.

This commit is contained in:
Brian J. Burg 2012-09-07 17:00:09 -07:00
parent cdd85d8d65
commit fd3ade2a3c
11 changed files with 413 additions and 236 deletions

View file

@ -3,8 +3,7 @@
// TODO: fail according to the css spec instead of failing when things
// are not as expected
use css::values::{TextColor, BackgroundColor, FontSize, Height, Width,
Display, StyleDeclaration};
use css::values::*;
// Disambiguate parsed Selector, Rule values from tokens
use css = css::values;
use tok = lexer;
@ -156,17 +155,20 @@ impl TokenReader : ParserMethods {
match tok {
tok::EndDescription => { break; }
tok::Description(prop, val) => {
let desc = match prop {
// TODO: have color parsing return an option instead of a real value
~"background-color" => parse_color(val).map(|res| BackgroundColor(res)),
~"color" => parse_color(val).map(|res| TextColor(res)),
~"display" => parse_display_type(val).map(|res| Display(res)),
~"font-size" => parse_font_size(val).map(|res| FontSize(res)),
~"height" => parse_size(val).map(|res| Height(res)),
~"width" => parse_size(val).map(|res| Width(res)),
let desc : Option<StyleDeclaration> = match prop {
// TODO: have color parsing return a ParseResult instead of a real value
~"background-color" => parse_color(val).map(|res| BackgroundColor(Specified(BgColor(res)))),
~"color" => parse_color(val).map(|res| Color(Specified(TextColor(res)))),
~"display" => parse_display_type(val).extract(|res| Display(res)),
~"font-size" => parse_font_size(val).extract(|res| FontSize(res)),
~"height" => parse_box_sizing(val).extract(|res| Height(res)),
~"width" => parse_box_sizing(val).extract(|res| Width(res)),
_ => { #debug["Recieved unknown style property '%s'", val]; None }
};
desc.map(|res| push(desc_list, res));
match desc {
Some(d) => push(desc_list, d),
None => { #debug["Couldn't parse value '%s' for property '%s'", val, prop] }
}
}
tok::Eof => { return None; }
tok::StartDescription | tok::Descendant | tok::Child | tok::Sibling

View file

@ -1,63 +1,76 @@
#[doc = "Helper functions to parse values of specific attributes."]
use css::values::{DisplayType, Inline, Block, DisplayNone};
use css::values::{Unit, Pt, Mm, Px, Percent, Auto};
use css::values::*;
use str::{pop_char, from_chars};
use float::from_str;
use option::map;
export parse_font_size;
export parse_size;
export parse_box_sizing;
export parse_display_type;
fn parse_unit(str : ~str) -> Option<Unit> {
fn parse_length(str : ~str) -> Option<Length> {
// TODO: use these once we stop lexing below
const PTS_PER_INCH: float = 72.0;
const CM_PER_INCH: float = 2.54;
const PX_PER_PT: float = 1.0 / 0.75;
match str {
s if s.ends_with(~"%") => from_str(str.substr(0, str.len() - 1)).map(|f| Percent(f)),
s if s.ends_with(~"in") => from_str(str.substr(0, str.len() - 2)).map(|f| Pt(72.0*f)),
s if s.ends_with(~"cm") => from_str(str.substr(0, str.len() - 2)).map(|f| Mm(10.0*f)),
s if s.ends_with(~"mm") => from_str(str.substr(0, str.len() - 2)).map(|f| Mm(f)),
s if s.ends_with(~"pt") => from_str(str.substr(0, str.len() - 2)).map(|f| Pt(f)),
s if s.ends_with(~"pc") => from_str(str.substr(0, str.len() - 2)).map(|f| Pt(12.0*f)),
s if s.ends_with(~"in") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * 72.0 * f)),
s if s.ends_with(~"cm") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(f / 2.54 * 72.0 * 1.0/0.75)),
s if s.ends_with(~"mm") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(f * 0.1 / 2.54 * 72.0 * 1.0/0.75)),
s if s.ends_with(~"pt") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * f)),
s if s.ends_with(~"pc") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(1.0/0.75 * 12.0 * f)),
s if s.ends_with(~"px") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(f)),
s if s.ends_with(~"ex") | s.ends_with(~"em") => fail ~"Em and Ex sizes not yet supported",
s if s.ends_with(~"em") => from_str(str.substr(0, str.len() - 2)).map(|f| Em(f)),
s if s.ends_with(~"ex") => from_str(str.substr(0, str.len() - 2)).map(|f| Em(0.5*f)),
_ => None,
}
}
fn parse_font_size(str : ~str) -> Option<Unit> {
// The default pixel size, not sure if this is accurate.
let default = 16.0;
fn parse_absolute_size(str : ~str) -> ParseResult<AbsoluteSize> {
match str {
~"xx-small" => Some(Px(0.6*default)),
~"x-small" => Some(Px(0.75*default)),
~"small" => Some(Px(8.0/9.0*default)),
~"medium" => Some(Px(default)),
~"large" => Some(Px(1.2*default)),
~"x-large" => Some(Px(1.5*default)),
~"xx-large" => Some(Px(2.0*default)),
~"smaller" => Some(Percent(80.0)),
~"larger" => Some(Percent(125.0)),
~"inherit" => Some(Percent(100.0)),
_ => parse_unit(str),
~"xx-small" => Value(XXSmall),
~"x-small" => Value(XSmall),
~"small" => Value(Small),
~"medium" => Value(Medium),
~"large" => Value(Large),
~"x-large" => Value(XLarge),
~"xx-large" => Value(XXLarge),
_ => Fail
}
}
fn parse_relative_size(str: ~str) -> ParseResult<RelativeSize> {
match str {
~"smaller" => Value(Smaller),
~"larger" => Value(Larger),
_ => Fail
}
}
fn parse_font_size(str: ~str) -> ParseResult<CSSFontSize> {
// TODO: complete me
Value(LengthSize(Px(14.0)))
}
// For width / height, and anything else with the same attribute values
fn parse_size(str : ~str) -> Option<Unit> {
fn parse_box_sizing(str : ~str) -> ParseResult<BoxSizing> {
match str {
~"auto" => Some(Auto),
~"inherit" => Some(Percent(100.0)),
_ => parse_unit(str),
~"auto" => Value(BoxAuto),
~"inherit" => CSSInherit,
_ => Fail,
}
}
fn parse_display_type(str : ~str) -> Option<DisplayType> {
fn parse_display_type(str : ~str) -> ParseResult<CSSDisplay> {
match str {
~"inline" => Some(Inline),
~"block" => Some(Block),
~"none" => Some(DisplayNone),
_ => { #debug["Recieved unknown display value '%s'", str]; None }
~"inline" => Value(DisplayInline),
~"block" => Value(DisplayBlock),
~"none" => Value(DisplayNone),
_ => { #debug["Recieved unknown display value '%s'", str]; Fail }
}
}

View file

@ -1,6 +1,6 @@
#[doc="Applies the appropriate CSS style to boxes."]
import dom::base::{Element, HTMLImageElement, Node};
import dom = dom::base;
import gfx::geometry::au_to_px;
import layout::base::{Box, BTree, NTree, LayoutData, SpecifiedStyle, ImageHolder,
BlockBox, InlineBox, IntrinsicBox, TextBox};
@ -8,7 +8,28 @@ import layout::traverse::{top_down_traversal};
import std::net::url::Url;
import resource::image_cache_task::ImageCacheTask;
import css::values::{Percent, Mm, Pt, Px, Auto, PtToPx, MmToPx};
import css::values::*;
trait ResolveMethods<T> {
pure fn initial() -> T;
}
impl CSSValue<CSSBackgroundColor> : ResolveMethods<CSSBackgroundColor> {
pure fn initial() -> CSSBackgroundColor { return BgTransparent; }
}
impl CSSValue<CSSDisplay> : ResolveMethods<CSSDisplay> {
pure fn initial() -> CSSDisplay { return DisplayInline; }
}
impl CSSValue<BoxSizing> : ResolveMethods<BoxSizing> {
pure fn initial() -> BoxSizing { return BoxAuto; }
}
impl CSSValue<CSSFontSize> : ResolveMethods<CSSFontSize> {
pure fn initial() -> CSSFontSize { return AbsoluteSize(Medium); }
}
struct StyleApplicator {
box: @Box;
@ -17,6 +38,7 @@ struct StyleApplicator {
reflow: fn~();
}
fn apply_style(box: @Box, doc_url: &Url, image_cache_task: ImageCacheTask, reflow: fn~()) {
let applicator = StyleApplicator {
box: box,
@ -28,6 +50,8 @@ fn apply_style(box: @Box, doc_url: &Url, image_cache_task: ImageCacheTask, reflo
applicator.apply_css_style();
}
// TODO: this is misleadingly-named. It is actually trying to resolve CSS 'inherit' values.
#[doc="A wrapper around a set of functions that can be applied as a top-down traversal of layout
boxes."]
fn inheritance_wrapper(box : @Box, doc_url: &Url, image_cache_task: ImageCacheTask, reflow: fn~()) {
@ -38,66 +62,51 @@ fn inheritance_wrapper(box : @Box, doc_url: &Url, image_cache_task: ImageCacheTa
reflow: reflow
};
applicator.apply_style();
inhereit_height(box);
inhereit_width(box);
inherit_fontsize(box);
inherit_height(box);
inherit_width(box);
}
/* Turns symbolic (abs, rel) and relative font sizes into absolute lengths */
fn inherit_fontsize(box : @Box) {
// TODO: complete this
return
}
#[doc="Compute the specified height of a layout box based on it's css specification and its
parent's height."]
fn inhereit_height(box : @Box) {
fn inherit_height(box : @Box) {
let style = box.node.get_specified_style();
let inherit_val = match box.tree.parent {
None => style.height.initial(),
Some(node) => node.appearance.height
};
box.appearance.height = match style.height {
None => Auto,
Some(h) => match h {
Auto | Px(*) => h,
Pt(*) => PtToPx(h),
Mm(*) => MmToPx(h),
Percent(em) => {
match box.tree.parent {
None => Auto,
Some(parent) => {
match parent.appearance.height {
//This is a poorly constrained case, so we ignore the percentage
Auto => Auto,
Px(f) => Px(em*f/100.0),
Percent(*) | Mm(*) | Pt(*) => {
fail ~"failed inheriting heights, parent should only be Px or Auto"
}
}
}
}
}
Initial => style.height.initial(),
Inherit => inherit_val,
Specified(val) => match val { // BoxSizing
BoxPercent(*) | BoxAuto | BoxLength(Px(_)) => val,
BoxLength(Em(n)) => BoxLength(Px(n * box.appearance.font_size.abs()))
}
}
}
#[doc="Compute the specified width of a layout box based on it's css specification and its
parent's width."]
fn inhereit_width(box : @Box) {
fn inherit_width(box : @Box) {
let style = box.node.get_specified_style();
let inherit_val = match box.tree.parent {
None => style.height.initial(),
Some(node) => node.appearance.width
};
box.appearance.width = match style.width {
None => Auto,
Some(h) => match h {
Auto | Px(*) => h,
Pt(*) => PtToPx(h),
Mm(*) => MmToPx(h),
Percent(em) => {
match box.tree.parent {
None => Auto,
Some(parent) => {
match parent.appearance.width {
//This is a poorly constrained case, so we ignore the percentage
Auto => Auto,
Px(f) => Px(em*f/100.0),
Percent(*) | Mm(*) | Pt(*) => {
fail ~"failed inheriting widths, parent should only be Px or Auto"
}
}
}
}
}
Initial => style.width.initial(),
Inherit => inherit_val,
Specified(val) => match val { // BoxSizing
BoxPercent(*) | BoxAuto | BoxLength(Px(_)) => val,
BoxLength(Em(n)) => BoxLength(Px(n * box.appearance.font_size.abs()))
}
}
}
@ -124,16 +133,9 @@ impl StyleApplicator {
// Right now, we only handle images.
do self.box.node.read |node| {
match node.kind {
~Element(element) => {
let style = self.box.node.get_specified_style();
self.box.appearance.background_color = match style.background_color {
Some(col) => col,
None => node.kind.default_color()
};
~dom::Element(element) => {
match element.kind {
~HTMLImageElement(*) => {
~dom::HTMLImageElement(*) => {
let url = element.get_attr(~"src");
if url.is_some() {
@ -192,7 +194,7 @@ mod test {
let g1_box = child_box.tree.first_child.get();
let g2_box = child_box.tree.last_child.get();
top_down_traversal(parent_box.get(), inhereit_height);
top_down_traversal(parent_box.get(), inherit_height);
assert parent_box.get().appearance.height == Px(100.0);
assert child_box.appearance.height == Auto;

View file

@ -4,9 +4,7 @@ import dom::base::{LayoutData};
import dom::base;
import base::{ElementData, Node, Text};
import values::{Selector, StyleDeclaration, FontSize, Display, TextColor, BackgroundColor,
Stylesheet, Element, Child, Descendant, Sibling, Attr, Exact, Exists, Includes,
StartsWith, Width, Height};
import values::*;
import styles::{SpecifiedStyle};
#[doc="Check if a CSS attribute matches the attribute of an HTML element."]
@ -169,12 +167,12 @@ impl Node : PrivStyleMethods {
fn update_style(decl : StyleDeclaration) {
self.aux(|layout| {
match decl {
BackgroundColor(col) => layout.specified_style.background_color = Some(col),
Display(dis) => layout.specified_style.display_type = Some(dis),
FontSize(size) => layout.specified_style.font_size = Some(size),
Height(size) => layout.specified_style.height = Some(size),
TextColor(col) => layout.specified_style.text_color = Some(col),
Width(size) => layout.specified_style.width = Some(size)
BackgroundColor(col) => layout.specified_style.background_color = col,
Display(dis) => layout.specified_style.display_type = dis,
FontSize(size) => layout.specified_style.font_size = size,
Height(size) => layout.specified_style.height = size,
Color(col) => layout.specified_style.text_color = col,
Width(size) => layout.specified_style.width = size
};
})
}

View file

@ -2,7 +2,7 @@
import std::arc::{ARC, get, clone};
import css::values::{DisplayType, DisplayNone, Inline, Block, Unit, Auto};
import css::values::*;
import css::values::Stylesheet;
import dom::base::{HTMLDivElement, HTMLHeadElement, HTMLImageElement, UnknownElement, HTMLScriptElement};
import dom::base::{Comment, Doctype, Element, Node, NodeKind, Text};
@ -10,19 +10,19 @@ import util::color::{Color, rgb};
import util::color::css_colors::{white, black};
import layout::base::{LayoutData, NTree};
type SpecifiedStyle = {mut background_color : Option<Color>,
mut display_type : Option<DisplayType>,
mut font_size : Option<Unit>,
mut height : Option<Unit>,
mut text_color : Option<Color>,
mut width : Option<Unit>
type SpecifiedStyle = {mut background_color : CSSValue<CSSBackgroundColor>,
mut display_type : CSSValue<CSSDisplay>,
mut font_size : CSSValue<CSSFontSize>,
mut height : CSSValue<BoxSizing>,
mut text_color : CSSValue<CSSColor>,
mut width : CSSValue<BoxSizing>
};
trait DefaultStyleMethods {
fn default_color() -> Color;
fn default_display_type() -> DisplayType;
fn default_width() -> Unit;
fn default_height() -> Unit;
fn default_display_type() -> CSSDisplay;
fn default_width() -> BoxSizing;
fn default_height() -> BoxSizing;
}
/// Default styles for various attributes in case they don't get initialized from CSS selectors.
@ -35,28 +35,28 @@ impl NodeKind : DefaultStyleMethods {
}
}
fn default_display_type() -> DisplayType {
fn default_display_type() -> CSSDisplay {
match self {
Text(*) => { Inline }
Text(*) => { DisplayInline }
Element(element) => {
match *element.kind {
HTMLDivElement => Block,
HTMLDivElement => DisplayBlock,
HTMLHeadElement => DisplayNone,
HTMLImageElement(*) => Inline,
HTMLImageElement(*) => DisplayInline,
HTMLScriptElement => DisplayNone,
UnknownElement => Inline,
UnknownElement => DisplayInline,
}
},
Comment(*) | Doctype(*) => DisplayNone
}
}
fn default_width() -> Unit {
Auto
fn default_width() -> BoxSizing {
BoxAuto
}
fn default_height() -> Unit {
Auto
fn default_height() -> BoxSizing {
BoxAuto
}
}
@ -70,12 +70,12 @@ impl NodeKind : DefaultStyleMethods {
fn empty_style_for_node_kind(kind: NodeKind) -> SpecifiedStyle {
let display_type = kind.default_display_type();
{mut background_color : None,
mut display_type : Some(display_type),
mut font_size : None,
mut height : None,
mut text_color : None,
mut width : None}
{mut background_color : Initial,
mut display_type : Specified(display_type),
mut font_size : Initial,
mut height : Initial,
mut text_color : Initial,
mut width : Initial}
}
trait StylePriv {

View file

@ -1,4 +1,5 @@
import util::color::Color;
use SharedColor = util::color::Color;
use cmp::Eq;
#[doc = "
Defines how css rules, both selectors and style specifications, are
@ -6,39 +7,156 @@ import util::color::Color;
http://www.w3.org/TR/CSS2/selector.html are represented by nested types.
"]
enum DisplayType {
Inline,
Block,
ListItem,
InlineBlock,
Table,
InlineTable,
TableRowGroup,
TableHeaderGroup,
TableFooterGroup,
TableRow,
TableColumnGroup,
TableColumn,
TableCell,
TableCaption,
// CSS Units
enum ParseResult<T> {
Value(T),
CSSInitial,
CSSInherit,
Fail
}
enum CSSValue<T : copy> {
Specified(T),
Initial,
Inherit
}
impl<T : copy> ParseResult<T> {
pure fn extract<U>(f: fn(CSSValue<T>) -> U) -> Option<U> { extract(self, f) }
}
pure fn extract<T : copy, U>(res: ParseResult<T>, f: fn(CSSValue<T>) -> U) -> Option<U> {
match res {
Fail => None,
CSSInitial => Some(f(Initial)),
CSSInherit => Some(f(Inherit)),
Value(x) => Some(f(Specified(x)))
}
}
impl<T: Eq copy> CSSValue<T> : Eq {
pure fn eq(&&other: CSSValue<T>) -> bool {
match (self, other) {
(Initial, Initial) => true,
(Inherit, Inherit) => true,
(Specified(a), Specified(b)) => a == b,
_ => false
}
}
}
enum Auto = ();
enum Length {
Em(float), // normalized to 'em'
Px(float) // normalized to 'px'
}
impl Length {
pure fn rel() -> float {
match self {
Em(x) => x,
_ => fail ~"attempted to access relative unit of an absolute length"
}
}
pure fn abs() -> float {
match self {
Em(x) => x,
_ => fail ~"attempted to access relative unit of an absolute length"
}
}
}
enum BoxSizing { // used by width, height, top, left, etc
BoxLength(Length),
BoxPercent(float),
BoxAuto
}
enum AbsoluteSize {
XXSmall,
XSmall,
Small,
Medium,
Large,
XLarge,
XXLarge
}
enum RelativeSize {
Larger,
Smaller
}
// CSS property values
enum CSSBackgroundAttachment {
BgAttachScroll,
BgAttachFixed
}
enum CSSBackgroundColor {
BgColor(SharedColor),
BgTransparent
}
enum CSSBackgroundRepeat {
BgRepeat,
BgRepeatX,
BgRepeatY,
BgNoRepeat
}
enum CSSColor {
TextColor(SharedColor)
}
enum CSSDirection {
DirectionLtr,
DirectionRtl
}
enum CSSDisplay {
DisplayInline,
DisplayBlock,
DisplayListItem,
DisplayInlineBlock,
DisplayTable,
DisplayInlineTable,
DisplayTableRowGroup,
DisplayTableHeaderGroup,
DisplayTableFooterGroup,
DisplayTableRow,
DisplayTableColumnGroup,
DisplayTableColumn,
DisplayTableCell,
DisplayTableCaption,
DisplayNone
}
enum Unit {
Auto,
Percent(float),
Mm(float),
Pt(float),
Px(float)
enum CSSFloat {
FloatLeft,
FloatRight,
FloatNone
}
enum CSSFontSize {
AbsoluteSize(AbsoluteSize),
RelativeSize(RelativeSize),
LengthSize(Length),
PercentSize(float)
}
// Stylesheet parts
enum StyleDeclaration {
BackgroundColor(Color),
Display(DisplayType),
FontSize(Unit),
Height(Unit),
TextColor(Color),
Width(Unit)
BackgroundColor(CSSValue<CSSBackgroundColor>),
Display(CSSValue<CSSDisplay>),
FontSize(CSSValue<CSSFontSize>),
Height(CSSValue<BoxSizing>),
Color(CSSValue<CSSColor>),
Width(CSSValue<BoxSizing>)
}
enum Attr{
@ -59,45 +177,80 @@ type Rule = (~[~Selector], ~[StyleDeclaration]);
type Stylesheet = ~[~Rule];
#[doc="Convert between units measured in millimeteres and pixels"]
pure fn MmToPx(u : Unit) -> Unit {
match u {
Mm(m) => Px(m * 3.7795),
_ => fail ~"Calling MmToPx on a unit that is not a Mm"
}
}
#[doc="Convert between units measured in points and pixels"]
pure fn PtToPx(u : Unit) -> Unit {
match u {
Pt(m) => Px(m * 1.3333),
_ => fail ~"Calling PtToPx on a unit that is not a Pt"
}
}
impl DisplayType: cmp::Eq {
pure fn eq(&&other: DisplayType) -> bool {
self as uint == other as uint
}
}
impl Unit: cmp::Eq {
pure fn eq(&&other: Unit) -> bool {
impl Length: cmp::Eq {
pure fn eq(&&other: Length) -> bool {
match (self, other) {
(Auto, Auto) => true,
(Auto, _) => false,
(Percent(a), Percent(b)) => a == b,
(Percent(*), _) => false,
(Mm(a), Mm(b)) => a == b,
(Mm(*), _) => false,
(Pt(a), Pt(b)) => a == b,
(Pt(*), _) => false,
(Em(a), Em(b)) => a == b,
(Px(a), Px(b)) => a == b,
(Px(*), _) => false
(_, _) => false
}
}
}
impl BoxSizing: cmp::Eq {
pure fn eq(&&other: BoxSizing) -> bool {
match (self, other) {
(BoxLength(a), BoxLength(b)) => a == b,
(BoxPercent(a), BoxPercent(b)) => a == b,
(BoxAuto, BoxAuto) => true,
(_, _) => false
}
}
}
impl AbsoluteSize: cmp::Eq {
pure fn eq(&&other: AbsoluteSize) -> bool {
self as uint == other as uint
}
}
impl RelativeSize: cmp::Eq {
pure fn eq(&&other: RelativeSize) -> bool {
self as uint == other as uint
}
}
impl CSSBackgroundColor: cmp::Eq {
pure fn eq(&&other: CSSBackgroundColor) -> bool {
match (self, other) {
(BgColor(a), BgColor(b)) => a == b,
(BgTransparent, BgTransparent) => true,
(_, _) => false
}
}
}
impl CSSColor: cmp::Eq {
pure fn eq(&&other: CSSColor) -> bool {
match (self, other) {
(TextColor(a), TextColor(b)) => a == b
}
}
}
impl CSSDisplay: cmp::Eq {
pure fn eq(&&other: CSSDisplay) -> bool {
self as uint == other as uint
}
}
impl CSSFontSize: cmp::Eq {
pure fn eq(&&other: CSSFontSize) -> bool {
match (self, other) {
(AbsoluteSize(a), AbsoluteSize(b)) => a == b,
(RelativeSize(a), RelativeSize(b)) => a == b,
(LengthSize(a), LengthSize(b)) => a == b,
(PercentSize(a), PercentSize(b)) => a == b,
(_, _) => false
}
}
}
/*
impl StyleDeclaration: cmp::Eq {
pure fn eq(&&other: StyleDeclaration) -> bool {
match (self, other) {
@ -105,18 +258,18 @@ impl StyleDeclaration: cmp::Eq {
(Display(a), Display(b)) => a == b,
(FontSize(a), FontSize(b)) => a == b,
(Height(a), Height(b)) => a == b,
(TextColor(a), TextColor(b)) => a == b,
(Color(a), Color(b)) => a == b,
(Width(a), Width(b)) => a == b,
(BackgroundColor(*), _)
| (Display(*), _)
| (FontSize(*), _)
| (Height(*), _)
| (TextColor(*), _)
| (Color(*), _)
| (Width(*), _) => false
}
}
}
}*/
impl Attr: cmp::Eq {
pure fn eq(&&other: Attr) -> bool {

View file

@ -1,7 +1,7 @@
#[doc="Fundamental layout structures and algorithms."]
import css::values::Unit;
import css::styles::SpecifiedStyle;
import css::values::{BoxSizing, Length, Px};
import dom::base::{Element, ElementKind, HTMLDivElement, HTMLImageElement, Node, NodeData};
import dom::base::{NodeKind};
import dom::rcu;
@ -42,13 +42,16 @@ impl BoxKind : cmp::Eq {
struct Appearance {
let mut background_image: Option<ImageHolder>;
let mut background_color: Color;
let mut width: Unit;
let mut height: Unit;
// TODO: create some sort of layout-specific enum to differentiate between
// relative and resolved values.
let mut width: BoxSizing;
let mut height: BoxSizing;
let mut font_size: Length;
new(kind: NodeKind) {
// TODO: these should come from initial() or elsewhere
self.font_size = Px(14.0);
self.background_image = None;
self.background_color = kind.default_color();
self.width = kind.default_width();
self.height = kind.default_height();
}

View file

@ -1,6 +1,6 @@
#[doc="Block layout."]
import css::values::{Px, Mm, Pt, Auto, Percent, Unit};
import css::values::*;
import geom::point::Point2D;
import geom::size::Size2D;
import gfx::geometry::{px_to_au, au};
@ -37,15 +37,15 @@ impl @Box : BlockLayoutMethods {
}
let height = match self.appearance.height {
Px(p) => px_to_au(p.to_int()),
Auto => au(current_height),
BoxLength(Px(p)) => px_to_au(p.to_int()),
BoxAuto => au(current_height),
_ => fail ~"inhereit_height failed, height is neither a Px or auto"
};
// FIXME: Width is wrong in the calculation below.
let width = match self.appearance.width {
Px(p) => px_to_au(p.to_int()),
Auto => self.bounds.size.width, // Do nothing here, width was set by top-down pass
BoxLength(Px(p)) => px_to_au(p.to_int()),
BoxAuto => self.bounds.size.width, // Do nothing here, width was set by top-down pass
_ => fail ~"inhereit_width failed, width is neither a Px or auto"
};

View file

@ -1,6 +1,6 @@
#[doc="Creates CSS boxes from a DOM."]
import css::values::{DisplayType, Block, Inline, DisplayNone};
import css::values::{CSSDisplay, DisplayBlock, DisplayInline, DisplayNone, Specified};
import dom::base::{ElementData, HTMLDivElement, HTMLImageElement, Element, Text, Node, Doctype, Comment};
import gfx::geometry::zero_size_au;
import layout::base::{Appearance, BTree, BlockBox, Box, BoxKind, InlineBox, IntrinsicBox, NTree};
@ -49,14 +49,14 @@ impl ctxt {
// Determine the child's display.
let disp = kid.get_specified_style().display_type;
if disp != Some(Inline) {
if disp != Specified(DisplayInline) {
self.finish_anonymous_box_if_necessary();
}
// Add the child's box to the current enclosing box or the current anonymous box.
match kid.get_specified_style().display_type {
Some(Block) => BTree.add_child(self.parent_box, kid_box.get()),
Some(Inline) => {
Specified(DisplayBlock) => BTree.add_child(self.parent_box, kid_box.get()),
Specified(DisplayInline) => {
let anon_box = match self.anon_box {
None => {
//
@ -75,7 +75,7 @@ impl ctxt {
};
BTree.add_child(anon_box, kid_box.get());
}
Some(DisplayNone) => {
Specified(DisplayNone) => {
// Nothing to do.
}
_ => { //hack for now
@ -96,21 +96,21 @@ impl ctxt {
// Determine the child's display.
let disp = kid.get_specified_style().display_type;
if disp != Some(Inline) {
if disp != Specified(DisplayInline) {
// TODO
}
// Add the child's box to the current enclosing box.
match kid.get_specified_style().display_type {
Some(Block) => {
Specified(DisplayBlock) => {
// TODO
#warn("TODO: non-inline display found inside inline box");
BTree.add_child(self.parent_box, kid_box.get());
}
Some(Inline) => {
Specified(DisplayInline) => {
BTree.add_child(self.parent_box, kid_box.get());
}
Some(DisplayNone) => {
Specified(DisplayNone) => {
// Nothing to do.
}
_ => { //hack for now
@ -125,9 +125,9 @@ impl ctxt {
self.parent_node.dump();
match self.parent_node.get_specified_style().display_type {
Some(Block) => self.construct_boxes_for_block_children(),
Some(Inline) => self.construct_boxes_for_inline_children(),
Some(DisplayNone) => { /* Nothing to do. */ }
Specified(DisplayBlock) => self.construct_boxes_for_block_children(),
Specified(DisplayInline) => self.construct_boxes_for_inline_children(),
Specified(DisplayNone) => { /* Nothing to do. */ }
_ => { //hack for now
}
}
@ -164,11 +164,11 @@ impl Node : PrivBoxBuilder {
~Element(element) => {
match (copy *element.kind, self.get_specified_style().display_type) {
(HTMLImageElement({size}), _) => Some(IntrinsicBox(@size)),
(_, Some(Block)) => Some(BlockBox),
(_, Some(Inline)) => Some(InlineBox),
(_, Some(DisplayNone)) => None,
(_, Some(_)) => Some(InlineBox),
(_, None) => {
(_, Specified(DisplayBlock)) => Some(BlockBox),
(_, Specified(DisplayInline)) => Some(InlineBox),
(_, Specified(DisplayNone)) => None,
(_, Specified(_)) => Some(InlineBox),
(_, _) => {
fail ~"The specified display style should be a default instead of none"
}
}

View file

@ -1,5 +1,6 @@
export build_display_list;
import css::values::{BgColor, BgTransparent, Specified};
import base::{Box, BTree, ImageHolder, TextBoxKind};
import dl = display_list;
import dom::base::{Text, NodeScope};
@ -65,7 +66,6 @@ fn box_to_display_items(list: dl::display_list, box: @Box, origin: Point2D<au>)
#debug("request to display a box from origin %?", origin);
let bounds = Rect(origin, copy box.bounds.size);
let col = box.appearance.background_color;
match box.kind {
TextBoxKind(subbox) => {
@ -96,10 +96,16 @@ fn box_to_display_items(list: dl::display_list, box: @Box, origin: Point2D<au>)
});
list.push(display_item);
} else {
#debug("Assigning color %? to box with bounds %?", col, bounds);
let col = box.appearance.background_color;
// DAC
// TODO: shouldn't need to unbox CSSValue by now
let boxed_color = box.node.get_specified_style().background_color;
let color = match boxed_color {
Specified(BgColor(c)) => c,
Specified(BgTransparent) | _ => util::color::rgba(0,0,0,0.0)
};
#debug("Assigning color %? to box with bounds %?", color, bounds);
list.push(dl::display_item({
item_type: dl::display_item_solid_color(col.red, col.green, col.blue),
item_type: dl::display_item_solid_color(color.red, color.green, color.blue),
bounds: bounds
}));
}

View file

@ -1,7 +1,7 @@
#[doc="Inline layout."]
import base::{Box, InlineBox, BTree};
import css::values::{Auto, Px};
import css::values::{BoxAuto, BoxLength, Px};
import dom::rcu;
import geom::point::Point2D;
import geom::size::Size2D;
@ -34,14 +34,14 @@ impl @Box : InlineLayout {
}
let height = match self.appearance.height {
Px(p) => px_to_au(p.to_int()),
Auto => au(current_height),
BoxLength(Px(p)) => px_to_au(p.to_int()),
BoxAuto => au(current_height),
_ => fail ~"inhereit_height failed, height is neither a Px or auto"
};
let width = match self.appearance.width {
Px(p) => px_to_au(p.to_int()),
Auto => au(i32::max(x, *self.bounds.size.width)),
BoxLength(Px(p)) => px_to_au(p.to_int()),
BoxAuto => au(i32::max(x, *self.bounds.size.width)),
_ => fail ~"inhereit_width failed, width is neither a Px or auto"
};