/[suikacvs]/markup/html/whatpm/Whatpm/CSS/Cascade.pm
Suika

Contents of /markup/html/whatpm/Whatpm/CSS/Cascade.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show annotations) (download)
Tue Jan 1 07:07:28 2008 UTC (18 years, 3 months ago) by wakaba
Branch: MAIN
Changes since 1.2: +61 -1 lines
++ whatpm/Whatpm/CSS/ChangeLog	1 Jan 2008 07:07:18 -0000
	* Cascade.pm (get_cascaded_value): It now should return |undef|
	for shorthand properties.
	(get_specified_value, get_computed_value): New methods.

	* Parser.pm: |initial|, |inherited|, and |compute| properties
	are added to property definitions.

2008-01-01  Wakaba  <wakaba@suika.fam.cx>

1 package Whatpm::CSS::Cascade;
2
3 require Whatpm::CSS::Parser; ## NOTE: For property definitions.
4 require Whatpm::CSS::SelectorsSerializer;
5 use Scalar::Util qw/refaddr/;
6
7 ## Cascading and value computations
8
9 sub new ($$) {
10 my $self = bless {style_sheets => []}, shift;
11 $self->{document} = shift;
12 return $self;
13 } # new
14
15 ## NOTE: This version does not support dynamic addition --- style
16 ## sheets must be added before any other operation.
17 ## NOTE: The $ss argument must be a value that can be interpreted as
18 ## an array reference of CSSStyleSheet objects.
19 ## NOTE: |type| and |media| attributes are not accounted by this
20 ## method (and any others in the class); CSSStyleSheet objects must
21 ## be filtered before they are passed to this method.
22 sub add_style_sheets ($$) {
23 my ($self, $ss) = @_;
24
25 push @{$self->{style_sheets}}, @$ss;
26 } # add_style_sheets
27
28 ## TODO: non-CSS presentation hints
29 ## TODO: style=""
30
31 sub ___associate_rules ($) {
32 my $self = shift;
33
34 my $selectors_to_elements;
35
36 for my $sheet (@{$self->{style_sheets}}) {
37 ## TODO: @media
38 ## TODO: @import
39 ## TODO: style sheet sources
40
41 for my $rule (@{$sheet->css_rules}) {
42 next if $rule->type != 1; # STYLE_RULE
43
44 my $elements_to_specificity = {};
45
46 for my $selector (@{$$rule->{_selectors}}) {
47 my $selector_str = Whatpm::CSS::SelectorsSerializer->serialize_test
48 ([$selector]);
49 unless ($selectors_to_elements->{$selector_str}) {
50 $selectors_to_elements->{$selector_str}
51 = $self->{document}->___query_selector_all ([$selector]);
52 }
53 next unless @{$selectors_to_elements->{$selector_str}};
54
55 my $selector_specificity
56 = Whatpm::CSS::SelectorsParser->get_selector_specificity
57 ($selector);
58 for (@{$selectors_to_elements->{$selector_str}}) {
59 my $current_specificity = $elements_to_specificity->{refaddr $_};
60 if ($selector_specificity->[0] > $current_specificity->[0] or
61 $selector_specificity->[1] > $current_specificity->[1] or
62 $selector_specificity->[2] > $current_specificity->[2] or
63 $selector_specificity->[3] > $current_specificity->[3]) {
64 $elements_to_specificity->{refaddr $_} = $selector_specificity;
65 }
66 }
67 }
68
69 my $sd = $rule->style;
70 for (keys %$elements_to_specificity) {
71 push @{$self->{element_to_sds}->{$_} ||= []},
72 [$sd, $elements_to_specificity->{$_}];
73 }
74 }
75 }
76
77 for my $eid (keys %{$self->{element_to_sds} or {}}) {
78 $self->{element_to_sds}->{$eid} = [sort {
79 $a->[1]->[0] <=> $b->[1]->[0] or
80 $a->[1]->[1] <=> $b->[1]->[1] or
81 $a->[1]->[2] <=> $b->[1]->[2] or
82 $a->[1]->[3] <=> $b->[1]->[3]
83 ## NOTE: Perl |sort| is stable.
84 } @{$self->{element_to_sds}->{$eid} or []}];
85 }
86 } # associate_rules
87
88 sub get_cascaded_value ($$$) {
89 my ($self, $element, $prop_name) = @_;
90 return undef unless $Whatpm::CSS::Parser::Prop->{$prop_name};
91
92 my $key = $Whatpm::CSS::Parser::Prop->{$prop_name}->{key};
93 return undef unless defined $key; ## Shorthand property or some.
94
95 my $value;
96 for my $sds (reverse @{$self->{element_to_sds}->{refaddr $element} or []}) {
97 my $vp = ${$sds->[0]}->{$key};
98 if (defined $vp->[1] and $vp->[1] eq 'important') {
99 return $vp->[0];
100 } else {
101 $value = $vp->[0] unless defined $value;
102 }
103 }
104
105 return $value; # might be |undef|.
106 } # get_cascaded_value
107
108 sub get_specified_value ($$$) {
109 my ($self, $element, $prop_name) = @_;
110
111 ## TODO: Remove {specified_value} caching, once we implement most
112 ## of CSS 2.1 properties and confirm that it makes almost non sence
113 ## because of its duplication with {computed_value} caching.
114
115 my $eid = refaddr $element;
116 unless (exists $self->{specified_value}->{$eid}->{$prop_name}) {
117 my $cascaded = $self->get_cascaded_value ($element, $prop_name);
118 $self->{specified_value}->{$eid}->{$prop_name} = $cascaded;
119
120 unless (defined $cascaded) {
121 my $prop_def = $Whatpm::CSS::Parser::Prop->{$prop_name};
122 if (defined $prop_def) {
123 if ($prop_def->{inherited}) {
124 my $parent_element = $element->manakai_parent_element;
125 if (defined $parent_element) {
126 $self->{specified_value}->{$eid}->{$prop_name}
127 = $self->get_computed_value ($parent_element, $prop_name);
128 } else {
129 $self->{specified_value}->{$eid}->{$prop_name}
130 = $prop_def->{initial};
131 }
132 } else {
133 $self->{specified_value}->{$eid}->{$prop_name}
134 = $prop_def->{initial};
135 }
136 } else {
137 $self->{specified_value}->{$eid}->{$prop_name} = undef;
138 }
139 }
140 }
141
142 ## NOTE: Always |undef| for shorthand properties.
143
144 return $self->{specified_value}->{$eid}->{$prop_name};
145 } # get_specified_value
146
147 sub get_computed_value ($$$) {
148 my ($self, $element, $prop_name) = @_;
149
150 my $eid = refaddr $element;
151 unless (exists $self->{computed_value}->{$eid}->{$prop_name}) {
152 my $prop_def = $Whatpm::CSS::Parser::Prop->{$prop_name};
153 if (defined $prop_def) {
154 $self->{computed_value}->{$eid}->{$prop_name}
155 = $prop_def->{compute}->($self, $element, $prop_name,
156 $self->get_specified_value
157 ($element, $prop_name));
158 } else {
159 $self->{computed_value}->{$eid}->{$prop_name} = undef;
160 }
161 }
162
163 ## NOTE: Always |undef| for shorthand properties.
164
165 return $self->{computed_value}->{$eid}->{$prop_name};
166 } # get_computed_value
167
168 1;
169 ## $Date: 2008/01/01 02:54:35 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24