4 |
push our @ISA, 'Message::IF::CSSStyleDeclaration', |
push our @ISA, 'Message::IF::CSSStyleDeclaration', |
5 |
'Message::IF::CSS2Properties'; |
'Message::IF::CSS2Properties'; |
6 |
|
|
7 |
|
my $serialize_value = sub ($$$) { |
8 |
|
my ($self, $prop_name, $value) = @_; |
9 |
|
if ($value->[0] eq 'NUMBER' or $value->[0] eq 'WEIGHT') { |
10 |
|
## TODO: What we currently do for 'font-weight' is different from |
11 |
|
## any browser for lighter/bolder cases. We need to fix this, but |
12 |
|
## how? |
13 |
|
return $value->[1]; ## TODO: big or small number cases? |
14 |
|
} elsif ($value->[0] eq 'DIMENSION') { |
15 |
|
return $value->[1] . $value->[2]; ## NOTE: This is what browsers do. |
16 |
|
} elsif ($value->[0] eq 'PERCENTAGE') { |
17 |
|
return $value->[1] . '%'; |
18 |
|
} elsif ($value->[0] eq 'KEYWORD') { |
19 |
|
return $value->[1]; |
20 |
|
} elsif ($value->[0] eq 'URI') { |
21 |
|
## NOTE: This is what browsers do. |
22 |
|
return 'url('.$value->[1].')'; |
23 |
|
} elsif ($value->[0] eq 'RGBA') { |
24 |
|
if ($value->[4] == 1) { |
25 |
|
return 'rgb('.$value->[1].', '.$value->[2].', '.$value->[3].')'; |
26 |
|
} elsif ($value->[4] == 0) { |
27 |
|
## TODO: check what browsers do... |
28 |
|
return 'transparent'; |
29 |
|
} else { |
30 |
|
return 'rgba('.$value->[1].', '.$value->[2].', '.$value->[3].', ' |
31 |
|
.$value->[4].')'; |
32 |
|
} |
33 |
|
} elsif ($value->[0] eq 'INHERIT') { |
34 |
|
return 'inherit'; |
35 |
|
} elsif ($value->[0] eq 'DECORATION') { |
36 |
|
my @v = (); |
37 |
|
push @v, 'underline' if $value->[1]; |
38 |
|
push @v, 'overline' if $value->[2]; |
39 |
|
push @v, 'line-through' if $value->[3]; |
40 |
|
push @v, 'blink' if $value->[4]; |
41 |
|
return 'none' unless @v; |
42 |
|
return join ' ', @v; |
43 |
|
} elsif ($value->[0] eq 'QUOTES') { |
44 |
|
return join ' ', map {'"'.$_.'"'} map {$_->[0], $_->[1]} @{$value->[1]}; |
45 |
|
## NOTE: The result string might not be a <'quotes'> if it contains |
46 |
|
## e.g. '"'. In addition, it might not be a <'quotes'> if |
47 |
|
## @{$value->[1]} is empty (which is unlikely as long as the implementation |
48 |
|
## is not broken). |
49 |
|
} elsif ($value->[0] eq 'CONTENT') { |
50 |
|
return join ' ', map { |
51 |
|
$_->[0] eq 'KEYWORD' ? $_->[1] : |
52 |
|
$_->[0] eq 'STRING' ? '"' . $_->[1] . '"' : |
53 |
|
$_->[0] eq 'URI' ? 'url(' . $_->[1] . ')' : |
54 |
|
$_->[0] eq 'ATTR' ? 'attr(' . $_->[2] . ')' : ## TODO: prefix |
55 |
|
$_->[0] eq 'COUNTER' ? 'counter(' . $_->[1] . ', ' . $_->[3] . ')' : |
56 |
|
$_->[0] eq 'COUNTERS' ? 'counters(' . $_->[1] . ', "' . $_->[2] . '", ' . $_->[3] . ')' : |
57 |
|
'' |
58 |
|
} @{$value}[1..$#$value]; |
59 |
|
} elsif ($value->[0] eq 'RECT') { |
60 |
|
## NOTE: Four components are DIMENSIONs. |
61 |
|
return 'rect(' . $value->[1]->[1].$value->[1]->[2] . ', ' |
62 |
|
. $value->[2]->[1].$value->[2]->[2] . ', ' |
63 |
|
. $value->[3]->[1].$value->[3]->[2] . ', ' |
64 |
|
. $value->[4]->[1].$value->[4]->[2] . ')'; |
65 |
|
} elsif ($value->[0] eq 'SETCOUNTER' or $value->[0] eq 'ADDCOUNTER') { |
66 |
|
return join ' ', map {$_->[0], $_->[1]} @$value[1..$#$value]; |
67 |
|
} elsif ($value->[0] eq 'FONT') { |
68 |
|
return join ', ', map { |
69 |
|
if ($_->[0] eq 'STRING') { |
70 |
|
'"'.$_->[1].'"'; ## NOTE: This is what Firefox does. |
71 |
|
} elsif ($_->[0] eq 'KEYWORD') { |
72 |
|
$_->[1]; ## NOTE: This is what Firefox does. |
73 |
|
} else { |
74 |
|
## NOTE: This should be an error. |
75 |
|
'""'; |
76 |
|
} |
77 |
|
} @$value[1..$#$value]; |
78 |
|
} elsif ($value->[0] eq 'CURSOR') { |
79 |
|
return join ', ', map { |
80 |
|
if ($_->[0] eq 'URI') { |
81 |
|
'url('.$_->[1].')'; ## NOTE: This is what Firefox does. |
82 |
|
} elsif ($_->[0] eq 'KEYWORD') { |
83 |
|
$_->[1]; |
84 |
|
} else { |
85 |
|
## NOTE: This should be an error. |
86 |
|
'""'; |
87 |
|
} |
88 |
|
} @$value[1..$#$value]; |
89 |
|
} else { |
90 |
|
return ''; |
91 |
|
} |
92 |
|
}; # $serialize_value |
93 |
|
|
94 |
sub ____new ($) { |
sub ____new ($) { |
95 |
return bless \{}, $_[0]; |
return bless \{}, $_[0]; |
96 |
} # ____new |
} # ____new |
105 |
|
|
106 |
if ($prop_def) { |
if ($prop_def) { |
107 |
no strict 'refs'; |
no strict 'refs'; |
108 |
if ($prop_def->{serialize}) { |
if (defined $prop_def->{key}) { |
109 |
*{ $method_name } = sub { |
*{ $method_name } = sub { |
110 |
## TODO: setter |
## TODO: setter |
111 |
|
|
112 |
my $self = $_[0]; |
my $self = $_[0]; |
113 |
my $value = $$self->{$prop_def->{key}}; |
my $value = $$self->{$prop_def->{key}}; |
114 |
if ($value) { |
if ($value) { |
115 |
return $prop_def->{serialize}->($self, $prop_def->{css}, $value->[0]); |
return $serialize_value->($self, $prop_def->{css}, $value->[0]); |
116 |
} else { |
} else { |
117 |
return ''; |
return ''; |
118 |
} |
} |
181 |
} |
} |
182 |
} else { |
} else { |
183 |
my $value = $$self->{$_}; |
my $value = $$self->{$_}; |
184 |
my $s = $prop_def->{serialize}->($self, $prop_def->{css}, $value->[0]); |
my $s = $serialize_value->($self, $prop_def->{css}, $value->[0]); |
185 |
if (length $s) { |
if (length $s) { |
186 |
$r .= ' ' . $prop_def->{css} . ': ' . $s; |
$r .= ' ' . $prop_def->{css} . ': ' . $s; |
187 |
$r .= ' ! ' . $value->[1] if length $value->[1]; |
$r .= ' ! ' . $value->[1] if length $value->[1]; |
215 |
my $prop_def = $Whatpm::CSS::Parser::Prop->{$prop_name}; |
my $prop_def = $Whatpm::CSS::Parser::Prop->{$prop_name}; |
216 |
return '' unless defined $prop_def; |
return '' unless defined $prop_def; |
217 |
|
|
218 |
if ($prop_def->{serialize}) { |
if (defined $prop_def->{key}) { |
219 |
my $v = ${$_[0]}->{$prop_def->{key}}; |
my $v = ${$_[0]}->{$prop_def->{key}}; |
220 |
return $v ? $v->[1] : ''; |
return $v ? $v->[1] : ''; |
221 |
} elsif ($prop_def->{serialize_shorthand} or |
} elsif ($prop_def->{serialize_shorthand} or |
281 |
my $value = $$self->{cascade}->get_computed_value |
my $value = $$self->{cascade}->get_computed_value |
282 |
($$self->{element}, $prop_def->{css}); |
($$self->{element}, $prop_def->{css}); |
283 |
if ($value) { |
if ($value) { |
284 |
return $prop_def->{serialize}->($self, $prop_def->{css}, $value); |
return $serialize_value->($self, $prop_def->{css}, $value); |
285 |
} else { |
} else { |
286 |
return ''; |
return ''; |
287 |
} |
} |
360 |
} else { |
} else { |
361 |
my $prop_value = $$self->{cascade}->get_computed_value |
my $prop_value = $$self->{cascade}->get_computed_value |
362 |
($$self->{element}, $prop_def->{css}); |
($$self->{element}, $prop_def->{css}); |
363 |
my $s = $prop_def->{serialize}->($self, $prop_def->{css}, $prop_value); |
my $s = $serialize_value->($self, $prop_def->{css}, $prop_value); |
364 |
if (length $s) { |
if (length $s) { |
365 |
$r .= ' ' . $prop_def->{css} . ': ' . $s; |
$r .= ' ' . $prop_def->{css} . ': ' . $s; |
366 |
$r .= ";\n"; |
$r .= ";\n"; |