Commit graph

248 commits

Author SHA1 Message Date
Andreas Kling
71d5dc510e LibWeb: Resolve CSS variables if present in SVG presentation attributes
SVG presentation attributes are parsed as CSS values, so we also need to
handle CSS variable expansion when handling them.

This (roughly) matches the behavior of other engines. It's also used on
the web, for example on https://stripe.com/ :^)
2023-05-24 06:43:21 +02:00
Andreas Kling
fb722e69f3 LibWeb: Resolve CSS custom properties on pseudo elements
The resolved property sets are stored with the element in a
per-pseudo-element array (same as for pseudo element layout nodes).

Longer term, we should stop storing this with elements entirely and make
it temporary state in StyleComputer somehow, so we don't waste memory
keeping all the resolved properties around.

This makes various gradients show up on https://shopify.com/ :^)
2023-05-17 20:37:29 +02:00
Andreas Kling
4005793e79 LibWeb: Handle CSS "color: currentcolor"
Per CSS-COLOR-4, when `color` is `currentcolor`, it should resolve to
the inherited value.
2023-05-10 15:36:34 +02:00
Andreas Kling
3f4de06fc2 LibWeb: Cache the root element font metrics when calculating them
The root element font metrics were getting queried again and again
during style computation. Before this change we would do some work to
recalculate them each time.

This patch simply caches them in a StyleComputer member. Since style
updates always start with the root element, we know that it'll be
up-to-date by the time we look at any other element.

Before this change, we were spending ~5% of CPU time on Google Groups
in root_element_font_metrics().
2023-05-08 12:13:20 +02:00
Andreas Kling
70db40c9b0 LibWeb: Don't include Layout/Node.h from DOM/Element.h
This required moving the CSS::StyleProperty destruct out of line.
2023-05-08 09:29:44 +02:00
Andreas Kling
3e62ab996d LibWeb: Put debug spam about unimplemented calc() expansion behind flag 2023-05-06 18:41:34 +02:00
Sam Atkins
f4d8a24fe4 LibWeb: Propagate errors from parse_css_value and property_initial_value 2023-05-06 08:07:28 +02:00
Sam Atkins
ba6d37ee6f LibWeb: Propagate errors when parsing StyleValues
This necessitated returning `nullptr` instead of just `{}` in a lot of
places. Also, some temporary hackiness in `parse_css_value()`: That
returns a special `ParseError` type already, so we now have a
`FIXME_TRY()` macro which logs the error and then returns a generic
`ParseError::InternalError` value. Eventually this macro will go away,
once I figure out how to deal with this more nicely.
2023-05-06 08:07:28 +02:00
Sam Atkins
d732a83de8 LibWeb: Propagate errors from absolutizing StyleValues 2023-05-06 08:07:28 +02:00
Sam Atkins
d16600a48b LibWeb: Propagate errors from StyleValue construction
Turns out we create a lot of these, mostly from places that don't return
ErrorOr. The yak stack grows.
2023-05-06 08:07:28 +02:00
Andreas Kling
610a7603a2 LibWeb: Implement more box type transformation edge cases
In particular, we now blockify layout internal boxes (e.g table parts)
by turning them into `block flow`. This fixes a crash when viewing
our GitHub repo :^)
2023-05-03 16:04:30 +02:00
Emil Militzer
fe40a7b664 LibWeb: Only change inside value during blockification 2023-05-02 20:27:28 +02:00
Emil Militzer
31e1be0438 LibWeb: Support multi-keyword syntax for CSS display property
The Display class already supported all specific values, and now they
will be parsed too. The display property now has a special type
DisplayStyleValue.
2023-05-02 20:27:28 +02:00
martinfalisse
22202715fc LibWeb: Parse grid-template property 2023-04-30 05:56:10 +02:00
Sam Atkins
3c171593f8 LibWeb: Merge StyleComputer root-element font-metric calculation methods
This saves us from doing a lot of the same work multiple times, when we
want both the root font size and its line height.
2023-04-29 16:23:50 +02:00
Sam Atkins
0679b4e0b9 LibWeb: Wrap font metrics into a struct
Rather than passing an increasingly-unwieldy number of font parameters
individually to every function that resolves lengths, let's wrap them
up.

This is frustratingly close to being `Gfx::FontPixelMetrics`, but bitmap
fonts cause issues: We choose the closest font to what the CSS
requests, but that might have a wildly different size than what the
page expects, so we have to fudge the numbers.

No behaviour changes.
2023-04-29 16:23:50 +02:00
Andreas Kling
c0b4083b02 LibWeb: Blockify pseudo elements that are flex items
When deciding on a box type transformation (blockify/inlinify) for a
pseudo element, we have to use the originating element as a reference
rather than the parent.

(The originating element *is* the parent for its pseudo elements.)
2023-04-27 18:29:02 +02:00
MacDue
b85d24b1f4 LibWeb: Expand background-position layers into x/y position lists
This fixes multi-layer backgrounds with background positions. This
is a little awkard, so maybe it would be better to refactor the
parsing code to make these lists directly, but right now this is
the simplest fix.
2023-04-03 20:54:36 +02:00
MacDue
bed55ac669 LibWeb: Parse and plumb background-position-x/y
This parses the new background-position-x/y longhands and properly
hooks up them up. This requires converting PositionStyleValue to
just contain two EdgeStyleValues so that it can be easily expanded
into the longhands.
2023-04-03 07:10:33 +02:00
Andreas Kling
8bb0be7d4f LibWeb: Don't apply presentational hints to associated pseudo elements
CSS properties generated by presentational hints in content attributes
should not leak into pseudo elements.
2023-04-02 15:00:06 +02:00
Andreas Kling
620a34a463 LibWeb: Don't apply element inline style to associated pseudo elements
An element's inline style, if present, should not leak into any pseudo
elements generated by that element.
2023-04-02 15:00:06 +02:00
Sam Atkins
53a4a31af2 LibWeb: Remove CalculatedStyleValue from Length 2023-03-30 21:29:50 +02:00
Andreas Kling
45f8542965 LibWeb: Actually visit rules and media queries in imported style sheets
Due to CSSImportRule::has_import_result() being backwards, we never
actually entered imported style sheets when traversing style rules or
media queries.

With this fixed, we no longer need the "collect style sheets" step in
StyleComputer, as normal for_each_effective_style_rule() will now
actually find all the rules. :^)
2023-03-30 16:54:15 +02:00
Sam Atkins
4c54c5d3dd LibWeb: Split StyleValueList out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
1d948f7462 LibWeb: Split UnresolvedStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
66cb7edffb LibWeb: Split TextDecorationStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
4b711932cc LibWeb: Split PercentageStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
f98634586e LibWeb: Split OverflowStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
7f6add1c6e LibWeb: Split NumericStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
fba2dacc7a LibWeb: Split ListStyleStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
9a84151169 LibWeb: Split LengthStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
76de017a51 LibWeb: Split IdentifierStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
486ef3df7f LibWeb: Split GridTrackPlacementStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
402845fe00 LibWeb: Split GridTrackPlacementShorthandStyleValue out of StyleValue 2023-03-25 16:56:04 +00:00
Sam Atkins
675cb3b9da LibWeb: Split GridAreaShorthandStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
87f920a299 LibWeb: Split FontStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
e24679f870 LibWeb: Split FlexFlowStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
273b9b4ca1 LibWeb: Split FlexStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
89ed8e59f9 LibWeb: Split FilterValueListStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
77b2826402 LibWeb: Split ColorStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
66bc816284 LibWeb: Split BorderRadiusStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
25114c159d LibWeb: Split BorderRadiusShorthandStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
1c03bc7a6f LibWeb: Split BorderStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Sam Atkins
92a0d4c0af LibWeb: Split BackgroundStyleValue out of StyleValue.{h,cpp} 2023-03-25 16:56:04 +00:00
Simon Wanner
554c4af90f LibWeb: Add support for the lh and rlh length units
Resolving these units is somewhat tricky because of their interaction
with both font-size and line-height, but this implementation seems to
work as tested in http://wpt.live/css/css-values/lh-unit-001.html and
http://wpt.live/css/css-values/lh-unit-002.html
2023-03-18 20:14:52 +01:00
Mathis Wiehl
f7d2392b6c LibWeb: Consider deprecated application/font-woff mime type
Though deprecated by IANA, `application/font-woff` is still in active
use as a MIME type for WOFF fonts by web servers throughout the wild
web.
2023-03-18 13:47:51 +01:00
Mathis Wiehl
3a45bba4e0 LibWeb: Load alternative font urls if others fail
We don't support all parts of the font formats we assume as "supported"
in the CSS parser. For example, if an open type font has a CFF table, we
reject loading it. This meant that until now, when such an
unsupported-supported font url was first in the list of urls, we
couldn't load it at all, even when we would support a later url.

To resolve that, try loading all font urls one after each other, in case
we are not able to load the higher priority one.

This also resolves a FIXME related to spec compliant url prioritization.
Our CSS parser already filters and prioritizes font src urls in
compliance with the spec. However, we still had to resort to brittle
file extension matching, because some websites don't set the `format`
and if the first url in a src list happened to be one we don't support,
the font could not be loaded at all. This now is unnecessary because we
can try and discard the urls instead.
2023-03-18 13:47:51 +01:00
Andreas Kling
062b8e5957 LibWeb: Print unimplemented calc() expressions in the debug log 2023-03-18 00:26:19 +01:00
Matthew Olsson
7c0c1c8f49 LibJS+LibWeb: Wrap raw JS::Cell*/& fields in GCPtr/NonnullGCPtr 2023-03-15 08:48:49 +01:00
Mathis Wiehl
3bd1d8bf6c LibWeb: Invalidate styles on font load
It is not sufficient to just invalidate layout when a new font has
loaded, because while it was loading we might have chosen a fallback
font-family value instead.

Invalidate style instead.
2023-03-14 21:07:44 +01:00
Andreas Kling
c598c092c2 LibWeb: Actually instantiate ::before/::after pseudo elements when found
Regressed in 3e970540b4.

Thanks to Luke for noticing the issue on YouTube! :^)
2023-03-14 18:47:20 +01:00
Andreas Kling
3e970540b4 LibWeb: Don't compute full style for ::before/::after unless matched
Before this patch, we would build full computed style for these pseudo
elements, for every DOM element, even if no ::before/::after selector
actually matched.

This was a colossal waste of time, and we can also just not do that.
Instead, just abort pseudo element style resolution early if no relevant
selectors matched. :^)
2023-03-14 16:53:03 +01:00
Andreas Kling
7bb7d87807 LibWeb: Resolve percentage line-height values before CSS inheritance
Percentage line-height values are relative to 1em (i.e the font-size
of the element). We have to resolve their computed values before
proceeding with inheritance.
2023-03-12 18:10:32 +01:00
Andreas Kling
7b55d79d3a LibWeb: Actually incorporate style from imported style sheets 2023-03-12 18:10:32 +01:00
Kenneth Myhra
be958a14cf LibWeb: Use from_deprecated_fly_string() instead of from_utf8()
Use FlyString::from_deprecated_fly_string() in these instances instead
of FlyString::from_utf8(). As we convert to new FlyString/String we want
to be aware of these potential unnecessary allocations.
2023-03-11 18:32:33 +00:00
Andreas Kling
a504ac3e2a Everywhere: Rename equals_ignoring_case => equals_ignoring_ascii_case
Let's make it clear that these functions deal with ASCII case only.
2023-03-10 13:15:44 +01:00
Andreas Kling
4bfdc4db17 LibWeb: Make CSS rule cache smarter about pseudo elements
Instead of putting every rule that matches a pseudo element in the
same bucket, let them go in the best ID/class/tag name bucket instead.
Then, add a flag to MatchingRule that says whether it contains a
pseudo element in the rightmost compound selector.

When deciding which selectors to run for an element, we can now simply
filter in/out pseudo element selectors as appropriate depending on what
we're trying to match.

This fixes an issue where pages using Font Awesome had 1700+ rules in the
pseudo-element rule cache. (This meant all those rules had to run
against every element twice or more while instantiating pseudo elements.)
2023-03-09 21:54:59 +01:00
Andreas Kling
72569bca1c LibWeb: Implement the CSS rule cache optimization for UA style as well
We were already sorting the author style selectors into buckets.
Now we do it for the built-in UA style as well.

This means less work for the selector engine everywhere :^)
2023-03-08 13:19:15 +01:00
Luke Wilde
f7ff1fd985 LibWeb: Remove CSS::Parser::ParsingContext's default constructor
This relied on pulling the current realm from the main thread VM, which
requires an execution context to be on the VM's stack. This heavily
relied on the dummy execution context that is always on the stack, for
example, when parsing the UA style sheets where no JavaScript is
running.
2023-03-07 11:51:12 +00:00
Andreas Kling
4c75d4af28 LibWeb: Stop using NonnullRefPtrVector for StyleValueVector 2023-03-06 23:46:35 +01:00
Andreas Kling
8a48246ed1 Everywhere: Stop using NonnullRefPtrVector
This class had slightly confusing semantics and the added weirdness
doesn't seem worth it just so we can say "." instead of "->" when
iterating over a vector of NNRPs.

This patch replaces NonnullRefPtrVector<T> with Vector<NNRP<T>>.
2023-03-06 23:46:35 +01:00
Andreas Kling
f11899f885 LibWeb+LibIDL: Fix (or paper over) various const-correctness issues
There's definitely stuff to iterate on here, but this takes care of
making the libraries compile with stricter RP and NNRP.
2023-02-21 00:54:04 +01:00
Sam Atkins
6cc5e09c71 LibWeb: Port StyleComputer to new Strings 2023-02-19 00:51:16 +01:00
Sam Atkins
1c77867c78 LibWeb: Port FontCache to new Strings 2023-02-19 00:51:16 +01:00
Sam Atkins
faab2fe101 LibWeb: Store stylesheet sources as StringViews 2023-02-19 00:51:16 +01:00
Sam Atkins
13d2111b74 LibWeb: Port Selector to new Strings
Also use `Infra::is_ascii_case_insensitive_match()` in some appropriate
places, after checking the specs.
2023-02-19 00:51:16 +01:00
Sam Atkins
c2f0b20d6b LibWeb: Port FontFace to new Strings 2023-02-19 00:51:16 +01:00
Sam Atkins
05c1b09621 LibWeb: Port CSS::Parser::Function to new Strings 2023-02-15 12:48:26 -05:00
Sam Atkins
7fc72d3838 LibWeb: Convert CSS Token value to new FlyString 2023-02-13 14:35:40 +00:00
Aliaksandr Kalenik
f58668031d LibWeb: Respect font-stretch in StyleComputer::compute_font 2023-02-05 08:06:06 +00:00
Aliaksandr Kalenik
1f4106842d LibGfx: Pass font width to FontDatabase::get()
Width need to be passed to `FontDatabase::get()` to resolve font name
unambiguously.
2023-02-05 08:06:06 +00:00
Aliaksandr Kalenik
ab99e95549 LibWeb: Parse font-stretch CSS property 2023-02-03 12:49:13 +00:00
martinfalisse
9bc001f410 LibWeb: Parse grid-area CSS property 2023-01-21 14:35:00 +01:00
Timothy Flynn
f3db548a3d AK+Everywhere: Rename FlyString to DeprecatedFlyString
DeprecatedFlyString relies heavily on DeprecatedString's StringImpl, so
let's rename it to A) match the name of DeprecatedString, B) write a new
FlyString class that is tied to String.
2023-01-09 23:00:24 +00:00
martinfalisse
ce0f41b9fb LibWeb+WebContent: Use new String class in CSS::StyleValue
Converts uses of DeprecatedString to String in StyleValue, and patches
surrounding files that depend on these functions.
2023-01-09 11:09:31 +01:00
Sam Atkins
4084c66ad2 LibWeb: Use CSS Pixels for viewport rects 2023-01-05 17:42:31 +01:00
Sam Atkins
8cc0bdf777 LibWeb: Resolve Lengths to CSSPixels 2023-01-05 17:42:31 +01:00
Sam Atkins
affc8a22ca LibWeb+WebContent: Convert BrowsingContext to new pixel units
This fixes a few glitches. We no longer give the page double the width
it should have, and we mark the correct area of the page as needing
repainting.
2023-01-05 17:42:31 +01:00
Vetrox
5080126095 LibWeb: CSS don't set resolve-failures (var/attr)
Previously when resolving an attr or var-defined property
with a 'not-set' value like this `property: var(--ValueNotSet)`,
we left the property unchanged (as an unresolved) and
added it to the computed-style of the element.
We still don't change the property but rather we now also don't set
unresolved properties in the computed-style.
This is an intended behavior.

The specification suggests that, on resolving an attr or var property
(custom properties) we have an invalid property when neither the
variable inside the var, nor the backup value could be resolved.

An invalid property must be inherited or defaulted depending on it's
type. We already do this with every 'untouched'
(as in m_property_values contains no entry for it) value.
So not setting the property results in an inherited (or initial)
value by a later-called function.

This also fixes another problem, where
`text-decoration: var(--NotSet)`
wouldn't be inherited because the computed-style of the
parent element hasn't set `text-decoration` but rather
all it's long-versions like `text-decoration-line` and so on.
2023-01-03 18:07:28 +01:00
Andreas Kling
f982400063 LibGfx: Rename TTF/TrueType to OpenType
OpenType is the backwards-compatible successor to TrueType, and the
format we're actually parsing in LibGfx. So let's call it that.
2022-12-21 08:44:22 +01:00
Thomas Queiroz
eacfcac932 LibWeb: Use HashMap::try_ensure_capacity in StyleComputer 2022-12-10 14:29:46 +01:00
Linus Groh
57dc179b1f Everywhere: Rename to_{string => deprecated_string}() where applicable
This will make it easier to support both string types at the same time
while we convert code, and tracking down remaining uses.

One big exception is Value::to_string() in LibJS, where the name is
dictated by the ToString AO.
2022-12-06 08:54:33 +01:00
Linus Groh
6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
Mateusz Górzyński
4dfdca74e2 LibWeb: Handle <relative-size> values in the font-size CSS property 2022-11-30 19:58:17 +00:00
Mateusz Górzyński
a551e02e5e LibWeb: Handle <absolute-size> values in the font-size CSS property 2022-11-30 19:58:17 +00:00
martinfalisse
9e6612c49b LibWeb: Parse CSS gap property
Including the legacy grid-gap, grid-column-gap and grid-row-gap
properties.
2022-11-07 10:06:07 +01:00
Andreas Kling
b33a2eb9b1 LibWeb: Inherit style across shadow tree boundaries
This makes the text in <input> inherit style from the <input> element.
2022-11-05 18:54:39 +01:00
Andreas Kling
43888b848c LibWeb: Resolve unresolved CSS calc() values in StyleComputer
When mixing calc() and var(), we're forced to delay resolving them until
we're in StyleComputer. Previously we'd just skip over them.

This patch handles calc() in the same pass as attr(). We reparse the
calc() value after var() expansion, and then try to resolve it to a
constant value if possible. If it's not possible, we leave the calc()
where it is, and maybe layout can figure it out later.

Note that I've only implemented resolution to integer and percentage in
this commit. There are more things a calc() could resolve to, and we
should implement those as well.
2022-11-02 22:42:48 +01:00
Andreas Kling
ab9aa9da0d LibWeb: Do CSS var() expansion in a separate pass
By expanding all the var() values first, we allow var() to occur
anywhere, even as arguments to CSS functions.
2022-11-02 22:42:48 +01:00
Andreas Kling
1e26d3d02d LibWeb: Make the initial containing block style have display:block
We always create a Layout::InitialContainingBlock for the ICB, but in a
future where we always honor the CSS::Display everywhere, we need to
make sure everyone has the right display values.
2022-10-06 15:29:38 +02:00
networkException
4230dbbb21 AK+Everywhere: Replace "protocol" with "scheme" url helpers
URL had properly named replacements for protocol(), set_protocol() and
create_with_file_protocol() already. This patch removes these function
and updates all call sites to use the functions named according to the
specification.

See https://url.spec.whatwg.org/#concept-url-scheme
2022-09-29 09:39:04 +01:00
Sam Atkins
54be317fa9 LibWeb: Use TokenStreams when expanding unresolved CSS values
This fixes a bug where any whitespace inside the `var()` or `attr()`
functions would make the StyleComputer fail to resolve them.
2022-09-27 19:36:31 +02:00
Andreas Kling
e72896e35e LibWeb: Get default fonts via Platform::FontPlugin
Instead of asking Gfx::FontDatabase for the "default font" and the
"default fixed-width font", we now proxy those requests out via
the Platform::FontPlugin. This will allow Ladybird to use other default
fonts as fallback.
2022-09-17 21:27:32 +02:00
Andreas Kling
a60c5166c6 LibWeb: Don't ignore data: URLs in @font-face src
Since data: URLs don't have a path, we shouldn't be checking for a TTF
or WOFF extension.

Thanks Timon for pointing this out! :^)
2022-09-15 12:45:00 +02:00
Andreas Kling
1c0fc75cb6 LibWeb: Fix bogus condition when checking CSS font file extensions
Thanks Idan for pointing this out! :^)
2022-09-15 01:20:35 +02:00
Andreas Kling
6d92c1d231 LibWeb: Be slightly better at @font-face rules with multiple sources
This patch improves @font-face loading when there are multiple src
values in two ways:

- Invalid/empty URLs are ignored
- Fonts with unsupported file extensions are ignored

This makes us load and display the emblem font on modern Reddit,
which is pretty neat! :^)
2022-09-14 21:46:34 +02:00
Andreas Kling
f64c175960 LibWeb: Invalidate layout whenever a CSS font is loaded
It's not enough to invalidate only the style, we have to do a full
layout invalidation since new fonts might mean new metrics, etc.
2022-09-14 21:24:31 +02:00
Andreas Kling
524ec95bcd LibWeb: Keep CSS sheets sorted in document tree order
This ensures that style is applied consistently, even if the document
has external CSS resources that don't always arrive in the same order.
2022-09-09 15:20:10 +02:00
Andreas Kling
8f0a48ef23 LibWeb: Make default CSS font settings match other browsers better
Let's make 16px the default font size instead of 10px. This makes our
layout results match those of other engines in many more cases.

Also make the h1-h6 element styles use relative (em) font sizes, also
matching other browsers.
2022-09-08 12:43:49 +02:00
Andreas Kling
5c2e3d1637 LibWeb+WebContent: Add abstraction layer for generic font families
Instead of hard-coding the names of system fonts to use for the CSS
generic fonts (like "sans-serif", "monospace", etc.) we now call out
to a Platform::FontPlugin and ask for the generic names.
2022-09-08 11:57:03 +02:00