Compare commits

...

128 Commits

Author SHA1 Message Date
Benjamin Otte 519b6c542c reftests: Add a test demonstrating unfortunate headerbar behavior
When centering a widget with a size between minimum and natural size,
the headerbar will always expand it as much as possible instead of
keeping it centered.
2019-04-12 22:29:11 +02:00
Benjamin Otte c6471ee874 reftests: Fix textview-margins test
The text is wider now that we changed the font properties, so account
for that.
2019-04-12 22:15:00 +02:00
Emmanuele Bassi 261b8c7ee6 Merge branch 'cache-reftest-images' into 'master'
ci: Cache the reftest artifacts

See merge request GNOME/gtk!744
2019-04-12 20:09:50 +00:00
Emmanuele Bassi f58f0732c2 ci: Cache the reftest artifacts
Keeping the reftest output images as artifacts of a job allows us to
browse them and download them straight from GitLab.
2019-04-12 20:58:29 +01:00
Emmanuele Bassi c5a4a26f06 Merge branch 'ci-update' into 'master'
ci: Install Monospace fonts

See merge request GNOME/gtk!742
2019-04-12 19:30:31 +00:00
Emmanuele Bassi faff08193a Merge branch 'fix-meson-on-macos-2' into 'master'
reftests: Use shared_library, not shared_module

See merge request GNOME/gtk!743
2019-04-12 19:30:19 +00:00
Emmanuele Bassi 3046358d38 ci: Update list of xfail tests
The label tests do not fail any more, because the CI image has Monospace
fonts; the textview-margins test started to fail on the CI image,
though.
2019-04-12 20:21:29 +01:00
Matthias Clasen e81f033ece Merge branch 'validate-alloc-size' into 'master'
Check the size of the g_new arguments

See merge request GNOME/gtk!741
2019-04-12 19:11:30 +00:00
Emmanuele Bassi 5c608fe070 ci: Install Monospace fonts
The reftests require them.
2019-04-12 20:09:10 +01:00
Matthias Clasen a2db956492 inspector: Show readonly property values 2019-04-12 15:08:01 -04:00
Matthias Clasen 8d51038cb1 inspector: Cosmetics 2019-04-12 15:08:01 -04:00
Matthias Clasen 86c86e0860 inspector: Revamp attribute and action info
This also needs to be turned into single-line data.
2019-04-12 15:08:01 -04:00
Matthias Clasen 324f5472a2 Fix a crash
We had a signal handler with a wrong signature, causing
a crash when looking  at the GtkSettings properties in
the inspector.
2019-04-12 15:08:01 -04:00
James Westman c20360dd98 reftests: Use shared_library, not shared_module
This allows Meson to run on macOS, where shared modules cannot be linked
against.
2019-04-12 14:04:01 -05:00
Emmanuele Bassi 1b6252ebf0 Merge branch 'default-request-mode' into 'master'
Add default GtkLayoutManagerClass.get_request_mode()

See merge request GNOME/gtk!738
2019-04-12 17:59:04 +00:00
Emmanuele Bassi b4c8ba4de7 Check the size of the g_new arguments
We're passing integers without validating their size, and newer GCC are
very cross about it, with warnings like:

    warning: argument 1 range [18446744071562067968, 18446744073709551615]
    exceeds maximum object size 9223372036854775807 [-Walloc-size-larger-than=]

We should check we're not overflowing the allocation size, by limiting
the range of values we can use.

First of all, we need to use `gsize` instead of a random `int`, since we're
allocating data.

Additionally, we need to check that the multiplication that computes the
size of the allocation doesn't overflow the maximum value of a `gsize`.
2019-04-12 18:58:34 +01:00
Benjamin Otte ad34f731e9 CI: Turn on reftests 2019-04-12 19:34:29 +02:00
Benjamin Otte 198207f1ff reftests: Mark the currently unfixed failures as XFAIL
They should be fixeed before 4.0 but the fixes are more involved. And we
want to start running the existing tests on CI, because they break
regularly and we want to catch that.
2019-04-12 19:34:29 +02:00
Benjamin Otte 6120f11ed3 reftests: Fix GtkFixed layout properties
GtkFixed was still using "x" and "y", when it should have been using
"position".
2019-04-12 19:34:29 +02:00
Benjamin Otte 0a440a804f reftests: Fix CSS for various tests
* :nth-child(first) => :first-child
* :nth-child(last) => :last-child
* Add semicolons at end of declarations
* Remove spaces between color functions (shade, alpha, ...) and args
2019-04-12 19:34:29 +02:00
Benjamin Otte 117fc68195 tests: Remove testboxcss
That test was cool in 2011, but hasn't been updated or used since then
because its features are now part of widget-factory and the inspector.

So let's remove it.
2019-04-12 19:34:29 +02:00
Benjamin Otte f310609a66 builder: Parse GskTransform properties
In particular, this allows parsing the GtkFixed position properties.
2019-04-12 19:34:29 +02:00
Benjamin Otte 8001c7d972 transform: Add gsk_transform_parse()
It uses the new CSS parser.
2019-04-12 19:34:29 +02:00
Benjamin Otte 023b695422 testsuite: Fix stylecontext test
Update the test to the stricter interpretation of the CSS specification
and the removal of custom additions.
2019-04-12 19:34:29 +02:00
Benjamin Otte ec6ce0707a testsuite: Update references for style test
We have more accurate section printouts now and they are used here.
2019-04-12 19:34:29 +02:00
Benjamin Otte f37573f8dc testsuite: Check errors not just for line, but for full range
Instead of just checking that the line of the error message is correct,
assert that start and end position are on the correct character offset.

Also fix all the tests to conform to this.
2019-04-12 19:34:29 +02:00
Benjamin Otte 49f8b571b9 testsuite: Update integer test
Make the test use an actual integer property that accepts negative
numbers (opacity) instead of one that wants units (margin-top) or
can't deal with negative numbers (everything else).
2019-04-12 19:34:29 +02:00
Benjamin Otte e1cd996617 selector: Inlcude : sign when reporting errors 2019-04-12 19:34:28 +02:00
Benjamin Otte 24cc721bc6 cssprovider: Mark whole @import statement on import error 2019-04-12 19:34:28 +02:00
Benjamin Otte d41580adfc calc: Have better error location range 2019-04-12 19:34:28 +02:00
Benjamin Otte 3ab65b7da2 csspositionvalue: Redo the parser
The old one incorrectly rejected "center left" and "center right".
2019-04-12 19:34:28 +02:00
Benjamin Otte 79238b0d8f cssparser: Add error functions that take locations
... and use them to report better error locations for the warning when
blocks aren't terminated properly.
2019-04-12 19:34:28 +02:00
Benjamin Otte 2e0a56665a css: Move gtkcsssection.[ch] into gtk/css 2019-04-12 19:34:28 +02:00
Benjamin Otte 76826cfa2f cssparser: Pass in error locations explicitly
And for the quick function, use the start/end location of the current
token.
2019-04-12 19:34:28 +02:00
Benjamin Otte 37671d2bd0 cssprovider: Redo error emission
Emit all errors via the parser, don't try to have a custom error
handling machinery.

The only exception is the initial file load error - we need to do that
one directly, because there is no parser.
2019-04-12 19:34:28 +02:00
Benjamin Otte 04d24b7cd2 csssection: Make printing functions public 2019-04-12 19:34:28 +02:00
Benjamin Otte 085d34cbb0 cssprovider: Advance parser to start of declaration
This way, the block will reference the right location.
2019-04-12 19:34:28 +02:00
Benjamin Otte 46143492a2 cssprovider: Change section handling
Instead of building a full tree of sections that then nobody cares
about, just create sections as necessary for when we use it in the
inspector.
2019-04-12 19:34:28 +02:00
Benjamin Otte a475d72d47 cssparser: Improve location APIs
1. Export multiple locations
2. Return the location instead of passing one in
2019-04-12 19:34:28 +02:00
Benjamin Otte a8f712b09a cssection: Return locations, not numbers
Now that we have GtkCssLocation, actually use it.
2019-04-12 19:34:28 +02:00
Benjamin Otte 2fb202187c css: Remove GtkCssSectionType
It's unused.
2019-04-12 19:34:28 +02:00
Benjamin Otte 207c0b32b4 csssection: Redo constructors
Remove the unused one and rename the old one to new_from_parser().
2019-04-12 19:34:28 +02:00
Benjamin Otte 35f60dc918 csssection: Store a GtkCssLocation 2019-04-12 19:34:28 +02:00
Benjamin Otte 1cd9396154 css: Review error messages
... and move them from _gtk_css_parser_error() to the proper new error
message.
2019-04-12 19:34:28 +02:00
Benjamin Otte de73ac980f css: Use gtk_css_parser_consume_any() for transition shorthand 2019-04-12 19:34:28 +02:00
Benjamin Otte acaec5f186 testsuite: Update parser tests to new errors
Some errors are now properly detected as unknown values when previously
they were just treated as syntax errors.
2019-04-12 19:34:28 +02:00
Benjamin Otte c8589a9a2f testsuite: Handle warnings in CSS tests 2019-04-12 19:34:28 +02:00
Benjamin Otte a31e5f7a8c cssshadow: Use gtk_css_parser_consume_any()
This way, the arguments can now really be speicified in any order.

A new testcase testing all the ordering possibilities has been added.
2019-04-12 19:34:28 +02:00
Benjamin Otte e0a01ba174 css: Redo for new parser
This commit is still way too big, but I couldn't make it smaller.

It transitions the old CSS parser to the new parser. CSS parsing is now
tokenized, everything else is probably still buggy.
2019-04-12 19:34:28 +02:00
Benjamin Otte 98e076b51e rgba: Add gdk_rgba_parser_parse()
This function is a (private) function to parse a GdkRGBA accoridng to
the CSS specs. We should probably use it for gdk_rgba_parse(), but that
would change the syntax we accept there...

This also introduces a dependency of libgdk on libgtkcss.

So far, no users for this function exist.
2019-04-12 19:34:28 +02:00
Benjamin Otte f3db19d694 Resurrect the CSS parser from the tokenizer branch
So far that parser is unused.
2019-04-12 19:34:28 +02:00
Benjamin Otte 607502ef43 cssparser: Add gtk_css_parser_consume_url()
Another slight renaming and semantics change.
2019-04-12 19:34:28 +02:00
Benjamin Otte acddc317da cssparser: Add gtk_css_parser_resolve_url()
Another slight change of semantics and naming for the new parser.
2019-04-12 19:34:28 +02:00
Benjamin Otte 7f99c1e588 cssparser: Split integer gettig into has/consume functions
We can't try to get an integer because ultimately integer getters
support the same shenanigans that numbers and percentages do with calc()
and whatnot.
2019-04-12 19:34:28 +02:00
Benjamin Otte 5f3e5a0406 cssparser: Add gtk_css_parser_try_delim()
For parsing single code point delimiters. Also port calc() to use this.
2019-04-12 19:34:28 +02:00
Benjamin Otte 23080d47b5 cssparser: Get rid of _gtk_css_parser_try_double()
Use gtk_css_parser_consume_number() everywhere instead.
2019-04-12 19:34:28 +02:00
Benjamin Otte f0d2f99239 cssparser: Add gtk_css_parser_consume_string()
Well, just rename _gtk_css_parser_read_string() for the new semantics,
but this sounds cooler.
2019-04-12 19:34:28 +02:00
Benjamin Otte e7b9ecc99a cssparser: Add gtk_css_parser_try_at_keyword() 2019-04-12 19:34:28 +02:00
Benjamin Otte dce8c11b07 cssparser: Drop _gtk_css_parser_has_prefix()
Replace it with has_ident/has_function. The old function is a typical
string matching API, not a tokenizing one.
2019-04-12 19:34:28 +02:00
Benjamin Otte 7ccec19501 parser: Get rid of _gtk_css_parser_is_eof()
Use gtk_css_parser_has_token() instead.
2019-04-12 19:34:28 +02:00
Benjamin Otte 93b643c44d css: Make font-weight an integer
This conforms to what Pango does and to the CSS4 spec. And it makes the
parsing code easier. So let's go for it.
2019-04-12 19:34:28 +02:00
Benjamin Otte 21616f6e2e cssimagescaled: Use gtk_css_parser_consume_function()
As part of that, adapt the syntax from
  -gtk-scaled( [<image>, <int>?]# )
to
  -gtk-scaled( [<image> <int>?]# )

because the commas should be used to separate distinct elements.

Note that almost nobody specifies the scale anyway.
2019-04-12 19:34:28 +02:00
Benjamin Otte 8157004068 easevalue: Use gtk_css_parser_consume_function() 2019-04-12 19:34:28 +02:00
Benjamin Otte 8d69bda27a cssimagelinear: Use gtk_css_parser_consume_function() 2019-04-12 19:34:28 +02:00
Benjamin Otte dbdb81f411 cssparser: Add gtk_css_parser_consume_ident()
And use it to fix the palette parser.
2019-04-12 19:34:28 +02:00
Benjamin Otte 28fbcf6abe shorthand: Use gtk_css_parser_try_ident() 2019-04-12 19:34:28 +02:00
Benjamin Otte 1fd339c46f cssimageradial: Use gtk_css_parser_consume_function() 2019-04-12 19:34:28 +02:00
Benjamin Otte b830bdca37 cssimagefallback: Use gtk_css_parser_consume_function() 2019-04-12 19:34:28 +02:00
Benjamin Otte 45bc4ed321 cssimagerecolor: Use gtk_css_parser_consume_function() 2019-04-12 19:34:28 +02:00
Benjamin Otte 3988847a05 reftests: Add a cross-fade syntax-checking reftest
Making sure all this newfangled code does what it says.
2019-04-12 19:34:28 +02:00
Benjamin Otte 9c862d7736 cross-fade: Make progress optional
Now we accept progress being unset and then dynamically compute it
on-demand.
2019-04-12 19:34:28 +02:00
Benjamin Otte d99ae4b6c2 cross-fade: Use gtk_css_parser_consume_any()
.. and gtk_css_parser_consume_function().

gtk_css_parser_consume_any() is a new function that implements the CSS
spec's any combinator ||.
2019-04-12 19:34:28 +02:00
Benjamin Otte 96f9cbcabf cssimage: Make cross-fade() an array
The new spec at https://drafts.csswg.org/css-images-4/#cross-fade-function
allows infinite images to cross-fade and we want to, too.
2019-04-12 19:34:28 +02:00
Benjamin Otte 3597f7e8b1 cssimageicontheme: Use gtk_css_parser_consume_function() 2019-04-12 19:34:28 +02:00
Benjamin Otte 38227dc972 cssfiltervalue: Use gtk_css_parser_consume_function() 2019-04-12 19:34:28 +02:00
Benjamin Otte aa50e92c65 csstransformvalue: Use gtk_css_parser_consume_function() 2019-04-12 19:34:28 +02:00
Benjamin Otte 753ad64cbc cssparser: Introduce gtk_css_parser_consume_function()
This is a vfunc-based function parser.
2019-04-12 19:34:28 +02:00
Benjamin Otte 3fb44ae651 cssparser: Add gtk_css_parser_try_token() 2019-04-12 19:34:28 +02:00
Benjamin Otte 76fb80f46c cssparser: Introduce gtk_css_parser_try_ident()
... and gtk_css_parser_has_function().
2019-04-12 19:34:28 +02:00
Benjamin Otte 684b6459f1 cssparser: Get rid of _gtk_css_parser_begins_with()
Replace it with calls to gtk_css_parser_has_token().
2019-04-12 19:34:28 +02:00
Benjamin Otte 904a9d0c98 parser: Add gtk_css_parser_has_token()
This is ithe first step towards converting the parsing code to use
tokens. For now, the topken type is just a magic enum value that only
works as-needed.
2019-04-12 19:34:28 +02:00
Benjamin Otte 32e256e5ab css: Split GtkCssLocation into its own file
And make the struct public, so we can use it in signal handlers.
2019-04-12 19:34:28 +02:00
Benjamin Otte d4d46e8125 csstokenizer: Add gtk_css_token_is_preserved() 2019-04-12 19:34:28 +02:00
Benjamin Otte 661720ef8b tokenizer: Pass error arg to read_token()
Instead of an error vfunc, have the tokenizer vfunc take a GError
argument. Note that even when an error is returned, there is still a
token to be read.
2019-04-12 19:34:28 +02:00
Benjamin Otte 013591d68d css: Add GtkCssTokenizer
This is copied from an old branch of mine.
2019-04-12 19:34:28 +02:00
Benjamin Otte a938c14d11 build: Add gtk-css static library
This library is meant to be the new CSS library that gets used from GDK,
GSK and GTK for string printing and parsing.

As a first step, move GtkCssProviderError into it.

While doing so, split it into GtkCssParserError (for critical problems)
and GtkCssParserWarning (for non-critical problems).
2019-04-12 19:34:28 +02:00
Emmanuele Bassi d6cc10ea74 Merge branch 'vulkan-warning' into 'master'
vulkan: Add missing enumeration value

See merge request GNOME/gtk!740
2019-04-12 17:26:52 +00:00
Emmanuele Bassi f25832455f vulkan: Add missing enumeration value
Vulkan 1.1.97 added VK_ERROR_INVALID_DEVICE_ADDRESS_EXT, and we now must
handle it.
2019-04-12 18:03:22 +01:00
Matthias Clasen 42ea95c54e inspector: Modernize action references
Now that we do inline editing, we need to
show this in a single line.
2019-04-12 13:01:19 -04:00
Matthias Clasen 46e7b44ffa inspector: Drop binding info
Thia was relying on non-public implementation details
and was broken since 2015.
2019-04-12 12:35:06 -04:00
Emmanuele Bassi a27737b04e Add default GtkLayoutManagerClass.get_request_mode()
Just like GtkContainer provides a default implementation of
GtkWidgetClass.get_request_mode(), we can do the same inside
GtkLayoutManager.

A default implementation preserves the behavior of existing widgets that
moved, or will move, to a GtkLayoutManager.
2019-04-12 17:10:30 +01:00
Matthias Clasen bd2d07e671 Merge branch 'inspector-props' into 'master'
inspector: Improve property list editing

See merge request GNOME/gtk!736
2019-04-12 15:20:26 +00:00
Matthias Clasen fde21b57cd inspector: Improve property list editing
Replace the treeview with popups on the property
page with a listbox with inline editing.
2019-04-12 11:12:55 -04:00
Benjamin Otte 637bd13f3f boxlayout: Remove unused variable 2019-04-12 16:32:00 +02:00
Emmanuele Bassi eadd90c22e ci: Use UTF-8 encoding for the test cover report
Since we're embedding text coming from the tests into the report, we
should specify an encoding for both the source JSON file and the target
XML file when opening them.
2019-04-12 13:56:17 +01:00
Emmanuele Bassi 279cb5717c Merge branch 'issue-1821' into 'master'
Fix get_request_mode for GtkBoxLayout

Closes #1821

See merge request GNOME/gtk!737
2019-04-12 12:54:08 +00:00
Emmanuele Bassi b91fbfd5a0 Fix get_request_mode for GtkBoxLayout
The default GtkWidgetClass.get_request_mode() is implemented by
GtkContainer; now that GtkBox uses a GtkBoxLayout, we need to implement
it inside the layout manager to preserve the same behavior as the old
GtkBox.

Fixes #1821
2019-04-12 13:14:44 +01:00
Chun-wei Fan 88086ea91a meson: Only use HarfBuzz fallback when needed
The current Meson releases have broken CMake support, meaning that it is
likely that HarfBuzz could not be located for Visual Studio builds
unless one handcrafts pkg-config files for it, which is both tedious and
error-prone.

Instead, use the existing mechanism for looking for the HarfBuzz headers
and libraries on Visual Studio first when it could not be found via
dependency(), and then use the fallback if it still could not be found.
2019-04-12 18:16:12 +08:00
Matthias Clasen 0842d084dd inspector: Cometic fixes for controllers
Add a frame, and make the rows not activatable.
2019-04-11 22:28:15 -04:00
Matthias Clasen 838b25177f inspector: Make rows activatable
Rows containing just a switch should be activatable,
and toggle the switch.
2019-04-11 22:06:16 -04:00
Matthias Clasen b39d0cec3c inspector: Fix css autosave
We were creating the directory with improper permissions.
2019-04-11 19:39:44 -04:00
Matthias Clasen f0c72bdc3b Adwaita: Add spacing to message dialogs
The text was running into the action area.
2019-04-11 19:39:44 -04:00
Benjamin Otte 427d216081 inspector: Enable by default
We don't want to stop people from being able to debug GTK applications
by default.

The keybinding also runs last in event delivery, so it doesn't override
existing keybindings anywhere and is therefor safe to enable.

The setting of course should remain, so people who want to lock down
installations, like for kiosks, can turn this off.
2019-04-12 00:39:24 +02:00
Aurimas Černius dc8b5f75a4 Updated Lithuanian translation 2019-04-11 22:50:00 +03:00
Matthias Clasen b6f2969872 Merge branch 'frame-clock' into 'master'
gdkframeclockidle: Don't permanently skew frame time

Closes #1612

See merge request GNOME/gtk!731
2019-04-11 17:23:03 +00:00
Jakub Steiner 6eed78e3de Adwaita: OSD set semi-opaque again
- forgot the bling bling
2019-04-11 15:35:24 +02:00
Jakub Steiner c4aa060118 Adwaita: less purple OSD style
- one of the bits that escaped the purple cast is the osd background color
2019-04-11 15:26:55 +02:00
Chris Williams 0bf4c2420d gdkframeclockidle: Don't permanently skew frame time
Since commit 3b2f9395, the frame time may be set into the future, so
only ensure monotonicity, and don't store the offset. This prevents the
frame time from becoming out of sync with g_get_monotonic_time().

Fixes #1612
2019-04-09 16:26:25 -04:00
Daniel Mustieles aac2556762 Update Spanish translation 2019-04-09 08:11:59 +00:00
Chris Williams f813bc1823 gdkframeclockidle: Remove unused struct member
compute_frame_time() has been using g_get_monotonic_time() instead of
GTimer since commit 7dfa4121.
2019-04-08 20:37:00 -04:00
Matthias Clasen e6631a7b66 Merge branch 'wip/cellrendererpixbuf-fallbacks' into 'master'
cellrendererpixbuf: Use fallback icons with icon-name

Closes #1809

See merge request GNOME/gtk!728
2019-04-08 15:09:40 +00:00
Iain Lane fbe0e32813 cellrendererpixbuf: Use fallback icons with icon-name
This gives us a better chance of finding an icon to show.

Closes: #1809
2019-04-08 15:05:51 +01:00
Matthias Clasen 2594593de2 Merge branch 'pick-insensitive2' into 'master'
Make picking insensitive widgets work again

Closes #1816 and #51

See merge request GNOME/gtk!727
2019-04-08 12:59:06 +00:00
Matthias Clasen ef982b7d46 Rename things
Rename the can-pick property to can-target,
and redo the pick flags with more descriptive names.
2019-04-08 08:42:25 -04:00
Ask Hjorth Larsen 0432b850c5 Updated Danish translation of gtk 2019-04-08 00:04:13 +02:00
Matthias Clasen 1b362d1f01 Keep a drawable check in gtk_widget_contains
If the widget is not drawable, it probably doesn't have
an allocation, so asking the question does not make much
sense.
2019-04-07 20:34:12 +00:00
Matthias Clasen 7ce968f297 Document GtkPickFlags 2019-04-07 17:27:58 +00:00
Matthias Clasen 0e15b4a367 inspector: Allow picking insensitive widgets again
Use the new argument to gtk_widget_pick to allow picking
insensitive widgets.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/51
2019-04-07 17:23:17 +00:00
Matthias Clasen de0942b0b8 tooltip: Allow tooltips on insensitive widgets again
Use the new argument to gtk_widget_pick to allow picking
insensitive widgets.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1816
2019-04-07 17:23:06 +00:00
Matthias Clasen b804235aea Add a flags argument to gtk_widget_pick
This will be used to let the inspector and other users
pick insensitive widgets again. For now, update all
callers to pass no flags, preserving the current
behavior.
2019-04-07 17:19:09 +00:00
Matthias Clasen 6bc32a3d5d widget: Drop the pick vfunc
The way to influence picking is to implement contains,
we no longer use the pick vfunc.
2019-04-07 17:00:51 +00:00
Matthias Clasen 5e24454764 window: Stop implementing pick
Treat popovers as a special-case for now.
2019-04-07 16:11:20 +00:00
Matthias Clasen d9cf0ff684 paned: Drop the pick vfunc
Implement contains on the handle, instead of pick on the paned.
2019-04-07 16:03:27 +00:00
Matthias Clasen 5b78a3048f gizmo: Add a contains_func
Let GtkGizmo override the contains() implementation.
Update all callers to pass NULL for the contains_func.
2019-04-07 15:47:24 +00:00
Matthias Clasen 676ac380cd widget: Make contains just be about position
Leave out reactiveness considerations here,
pick will handle those.
2019-04-07 15:18:37 +00:00
Matthias Clasen dce2c58799 widget: Make contains respect rounded borders
We have the api for this now.
2019-04-07 15:18:37 +00:00
Matthias Clasen f3d1666394 Merge branch 'treeview-expander-fix' into 'master'
treeview: Make expanders work again

Closes #1814

See merge request GNOME/gtk!725
2019-04-07 15:16:23 +00:00
Matthias Clasen 8af0782261 treeview: Make expanders work again
These were broken by the crossing event unification.
We are now generating some more crossing events, and
the treeview was not looking closely enough at the
ones it gets.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1814
2019-04-07 12:16:20 +00:00
287 changed files with 14862 additions and 9157 deletions
+3 -2
View File
@@ -13,7 +13,7 @@ stages:
- subprojects/pango/
fedora-x86_64:
image: registry.gitlab.gnome.org/gnome/gtk/master:v3
image: registry.gitlab.gnome.org/gnome/gtk/master:v4
stage: build
script:
- bash -x ./.gitlab-ci/test-docker.sh
@@ -26,6 +26,7 @@ fedora-x86_64:
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
- "${CI_PROJECT_DIR}/_build/report.xml"
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*.png"
cache:
key: "$CI_JOB_NAME"
<<: *cache-paths
@@ -99,7 +100,7 @@ flatpak-master:icon-browser:
<<: *flatpak-master
pages:
image: registry.gitlab.gnome.org/gnome/gtk/master:v3
image: registry.gitlab.gnome.org/gnome/gtk/master:v4
stage: deploy
script:
- meson -Ddocumentation=true _build .
+1
View File
@@ -11,6 +11,7 @@ RUN dnf -y install \
ccache \
colord-devel \
cups-devel \
dejavu-sans-mono-fonts \
desktop-file-utils \
elfutils-libelf-devel \
fribidi-devel \
+2 -2
View File
@@ -19,11 +19,11 @@ aparser.add_argument('--branch', metavar='NAME',
default='master')
aparser.add_argument('--output', metavar='FILE',
help='The output file, stdout by default',
type=argparse.FileType('w'),
type=argparse.FileType('w', encoding='UTF-8'),
default=sys.stdout)
aparser.add_argument('infile', metavar='FILE',
help='The input testlog.json, stdin by default',
type=argparse.FileType('r'),
type=argparse.FileType('r', encoding='UTF-8'),
default=sys.stdin)
args = aparser.parse_args()
+1 -1
View File
@@ -2,7 +2,7 @@
set -e
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v3"
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v4"
sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \
--file "Dockerfile" .
-1
View File
@@ -32,7 +32,6 @@ xvfb-run -a -s "-screen 0 1024x768x24" \
--print-errorlogs \
--suite=gtk \
--no-suite=gtk:gsk \
--no-suite=gtk:reftest \
--no-suite=gtk:a11y
# Save the exit code
+8 -5
View File
@@ -13,19 +13,22 @@ show_parsing_error (GtkCssProvider *provider,
const GError *error,
GtkTextBuffer *buffer)
{
const GtkCssLocation *start_location, *end_location;
GtkTextIter start, end;
const char *tag_name;
start_location = gtk_css_section_get_start_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&start,
gtk_css_section_get_start_line (section),
gtk_css_section_get_start_position (section));
start_location->lines,
start_location->line_bytes);
end_location = gtk_css_section_get_end_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&end,
gtk_css_section_get_end_line (section),
gtk_css_section_get_end_position (section));
end_location->lines,
end_location->line_bytes);
if (g_error_matches (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_DEPRECATED))
if (error->domain == GTK_CSS_PARSER_WARNING)
tag_name = "warning";
else
tag_name = "error";
+9 -5
View File
@@ -13,19 +13,23 @@ show_parsing_error (GtkCssProvider *provider,
const GError *error,
GtkTextBuffer *buffer)
{
const GtkCssLocation *start_location, *end_location;
GtkTextIter start, end;
const char *tag_name;
start_location = gtk_css_section_get_start_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&start,
gtk_css_section_get_start_line (section),
gtk_css_section_get_start_position (section));
start_location->lines,
start_location->line_bytes);
end_location = gtk_css_section_get_end_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&end,
gtk_css_section_get_end_line (section),
gtk_css_section_get_end_position (section));
end_location->lines,
end_location->line_bytes);
if (g_error_matches (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_DEPRECATED))
if (error->domain == GTK_CSS_PARSER_WARNING)
tag_name = "warning";
else
tag_name = "error";
+9 -5
View File
@@ -12,19 +12,23 @@ show_parsing_error (GtkCssProvider *provider,
const GError *error,
GtkTextBuffer *buffer)
{
const GtkCssLocation *start_location, *end_location;
GtkTextIter start, end;
const char *tag_name;
start_location = gtk_css_section_get_start_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&start,
gtk_css_section_get_start_line (section),
gtk_css_section_get_start_position (section));
start_location->lines,
start_location->line_bytes);
end_location = gtk_css_section_get_end_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&end,
gtk_css_section_get_end_line (section),
gtk_css_section_get_end_position (section));
end_location->lines,
end_location->line_bytes);
if (g_error_matches (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_DEPRECATED))
if (error->domain == GTK_CSS_PARSER_WARNING)
tag_name = "warning";
else
tag_name = "error";
+8 -5
View File
@@ -11,19 +11,22 @@ show_parsing_error (GtkCssProvider *provider,
const GError *error,
GtkTextBuffer *buffer)
{
const GtkCssLocation *start_location, *end_location;
GtkTextIter start, end;
const char *tag_name;
start_location = gtk_css_section_get_start_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&start,
gtk_css_section_get_start_line (section),
gtk_css_section_get_start_position (section));
start_location->lines,
start_location->line_bytes);
end_location = gtk_css_section_get_end_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&end,
gtk_css_section_get_end_line (section),
gtk_css_section_get_end_position (section));
end_location->lines,
end_location->line_bytes);
if (g_error_matches (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_DEPRECATED))
if (error->domain == GTK_CSS_PARSER_WARNING)
tag_name = "warning";
else
tag_name = "error";
+2 -2
View File
@@ -243,7 +243,7 @@ pressed_cb (GtkGesture *gesture,
GtkWidget *child;
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
child = gtk_widget_pick (widget, x, y);
child = gtk_widget_pick (widget, x, y, GTK_PICK_DEFAULT);
if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_SECONDARY)
{
@@ -320,7 +320,7 @@ released_cb (GtkGesture *gesture,
GtkWidget *child;
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
child = gtk_widget_pick (widget, x, y);
child = gtk_widget_pick (widget, x, y, 0);
if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_PRIMARY)
{
+1 -1
View File
@@ -57,7 +57,7 @@ do_overlay (GtkWidget *do_widget)
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), vbox);
gtk_widget_set_can_pick (vbox, FALSE);
gtk_widget_set_can_target (vbox, FALSE);
gtk_widget_set_halign (vbox, GTK_ALIGN_CENTER);
gtk_widget_set_valign (vbox, GTK_ALIGN_CENTER);
+2 -2
View File
@@ -66,13 +66,13 @@ do_overlay2 (GtkWidget *do_widget)
image = gtk_picture_new_for_resource ("/overlay2/decor1.png");
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), image);
gtk_widget_set_can_pick (image, FALSE);
gtk_widget_set_can_target (image, FALSE);
gtk_widget_set_halign (image, GTK_ALIGN_START);
gtk_widget_set_valign (image, GTK_ALIGN_START);
image = gtk_picture_new_for_resource ("/overlay2/decor2.png");
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), image);
gtk_widget_set_can_pick (image, FALSE);
gtk_widget_set_can_target (image, FALSE);
gtk_widget_set_halign (image, GTK_ALIGN_END);
gtk_widget_set_valign (image, GTK_ALIGN_END);
+1 -1
View File
@@ -228,7 +228,7 @@ puzzle_button_pressed (GtkGestureMultiPress *gesture,
int l, t, i;
int pos;
child = gtk_widget_pick (grid, x, y);
child = gtk_widget_pick (grid, x, y, GTK_PICK_DEFAULT);
if (!child)
{
+2
View File
@@ -152,6 +152,8 @@ gsk_transform_get_category
<SUBSECTION>
gsk_transform_print
gsk_transform_to_string
gsk_transform_parse
<SUBSECTION>
gsk_transform_to_matrix
gsk_transform_to_2d
gsk_transform_to_affine
+14 -12
View File
@@ -4507,6 +4507,7 @@ gtk_widget_compute_bounds
gtk_widget_compute_transform
gtk_widget_compute_point
gtk_widget_contains
GtkPickFlags
gtk_widget_pick
gtk_widget_get_can_default
gtk_widget_set_can_default
@@ -4515,8 +4516,8 @@ gtk_widget_set_can_focus
gtk_widget_get_focus_on_click
gtk_widget_set_focus_on_click
gtk_widget_set_focus_child
gtk_widget_get_can_pick
gtk_widget_set_can_pick
gtk_widget_get_can_target
gtk_widget_set_can_target
gtk_widget_get_has_surface
gtk_widget_set_has_surface
gtk_widget_get_sensitive
@@ -5085,20 +5086,21 @@ gtk_css_provider_load_from_path
gtk_css_provider_load_from_resource
gtk_css_provider_new
gtk_css_provider_to_string
GTK_CSS_PROVIDER_ERROR
GtkCssProviderError
GTK_CSS_PARSER_ERROR
GtkCssParserError
GtkCssParserWarning
<SUBSECTION>
GtkCssLocation
GtkCssSection
GtkCssSectionType
gtk_css_section_get_end_line
gtk_css_section_get_end_position
gtk_css_section_get_file
gtk_css_section_get_parent
gtk_css_section_get_section_type
gtk_css_section_get_start_line
gtk_css_section_get_start_position
gtk_css_section_new
gtk_css_section_ref
gtk_css_section_unref
gtk_css_section_print
gtk_css_section_to_string
gtk_css_section_get_file
gtk_css_section_get_parent
gtk_css_section_get_start_location
gtk_css_section_get_end_location
<SUBSECTION Standard>
GTK_TYPE_CSS_PROVIDER
GTK_CSS_PROVIDER
+4 -17
View File
@@ -38,9 +38,6 @@
struct _GdkFrameClockIdlePrivate
{
GTimer *timer;
/* timer_base is used to avoid ever going backward */
gint64 timer_base;
gint64 frame_time;
gint64 min_next_frame_time;
gint64 sleep_serial;
@@ -161,22 +158,12 @@ compute_frame_time (GdkFrameClockIdle *idle)
{
GdkFrameClockIdlePrivate *priv = idle->priv;
gint64 computed_frame_time;
gint64 elapsed;
elapsed = g_get_monotonic_time () + priv->timer_base;
if (elapsed < priv->frame_time)
{
/* clock went backward. adapt to that by forevermore increasing
* timer_base. For now, assume we've gone forward in time 1ms.
*/
/* hmm. just fix GTimer? */
computed_frame_time = g_get_monotonic_time ();
/* ensure monotonicity of frame time */
if (computed_frame_time <= priv->frame_time)
computed_frame_time = priv->frame_time + 1;
priv->timer_base += (priv->frame_time - elapsed) + 1;
}
else
{
computed_frame_time = elapsed;
}
return computed_frame_time;
}
+183 -1
View File
@@ -23,7 +23,9 @@
*/
#include "config.h"
#include "gdkrgba.h"
#include "gdkrgbaprivate.h"
#include <string.h>
#include <errno.h>
#include <math.h>
@@ -393,3 +395,183 @@ gdk_rgba_to_string (const GdkRGBA *rgba)
alpha);
}
}
static gboolean
parse_color_channel_value (GtkCssParser *parser,
double *value,
gboolean is_percentage)
{
if (is_percentage)
{
if (!gtk_css_parser_consume_percentage (parser, value))
return FALSE;
*value = CLAMP (*value, 0.0, 100.0) / 100.0;
return TRUE;
}
else
{
if (!gtk_css_parser_consume_number (parser, value))
return FALSE;
*value = CLAMP (*value, 0.0, 255.0) / 255.0;
return TRUE;
}
}
static guint
parse_color_channel (GtkCssParser *parser,
guint arg,
gpointer data)
{
GdkRGBA *rgba = data;
switch (arg)
{
case 0:
/* We abuse rgba->alpha to store if we use percentages or numbers */
if (gtk_css_token_is (gtk_css_parser_get_token (parser), GTK_CSS_TOKEN_PERCENTAGE))
rgba->alpha = 1.0;
else
rgba->alpha = 0.0;
if (!parse_color_channel_value (parser, &rgba->red, rgba->alpha != 0.0))
return 0;
return 1;
case 1:
if (!parse_color_channel_value (parser, &rgba->green, rgba->alpha != 0.0))
return 0;
return 1;
case 2:
if (!parse_color_channel_value (parser, &rgba->blue, rgba->alpha != 0.0))
return 0;
return 1;
case 3:
if (!gtk_css_parser_consume_number (parser, &rgba->alpha))
return 0;
rgba->alpha = CLAMP (rgba->alpha, 0.0, 1.0);
return 1;
default:
g_assert_not_reached ();
return 0;
}
}
static gboolean
rgba_init_chars (GdkRGBA *rgba,
const char s[8])
{
guint i;
for (i = 0; i < 8; i++)
{
if (!g_ascii_isxdigit (s[i]))
return FALSE;
}
rgba->red = (g_ascii_xdigit_value (s[0]) * 16 + g_ascii_xdigit_value (s[1])) / 255.0;
rgba->green = (g_ascii_xdigit_value (s[2]) * 16 + g_ascii_xdigit_value (s[3])) / 255.0;
rgba->blue = (g_ascii_xdigit_value (s[4]) * 16 + g_ascii_xdigit_value (s[5])) / 255.0;
rgba->alpha = (g_ascii_xdigit_value (s[6]) * 16 + g_ascii_xdigit_value (s[7])) / 255.0;
return TRUE;
}
gboolean
gdk_rgba_parser_parse (GtkCssParser *parser,
GdkRGBA *rgba)
{
const GtkCssToken *token;
token = gtk_css_parser_get_token (parser);
if (gtk_css_token_is_function (token, "rgb"))
{
if (!gtk_css_parser_consume_function (parser, 3, 3, parse_color_channel, rgba))
return FALSE;
rgba->alpha = 1.0;
return TRUE;
}
else if (gtk_css_token_is_function (token, "rgba"))
{
return gtk_css_parser_consume_function (parser, 4, 4, parse_color_channel, rgba);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_UNRESTRICTED))
{
const char *s = token->string.string;
switch (strlen (s))
{
case 3:
if (!rgba_init_chars (rgba, (char[8]) {s[0], s[0], s[1], s[1], s[2], s[2], 'F', 'F' }))
{
gtk_css_parser_error_value (parser, "Hash code is not a valid hex color.");
return FALSE;
}
break;
case 4:
if (!rgba_init_chars (rgba, (char[8]) {s[0], s[0], s[1], s[1], s[2], s[2], s[3], s[3] }))
{
gtk_css_parser_error_value (parser, "Hash code is not a valid hex color.");
return FALSE;
}
break;
case 6:
if (!rgba_init_chars (rgba, (char[8]) {s[0], s[1], s[2], s[3], s[4], s[5], 'F', 'F' }))
{
gtk_css_parser_error_value (parser, "Hash code is not a valid hex color.");
return FALSE;
}
break;
case 8:
if (!rgba_init_chars (rgba, s))
{
gtk_css_parser_error_value (parser, "Hash code is not a valid hex color.");
return FALSE;
}
break;
default:
gtk_css_parser_error_value (parser, "Hash code is not a valid hex color.");
return FALSE;
break;
}
gtk_css_parser_consume_token (parser);
return TRUE;
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
if (gtk_css_token_is_ident (token, "transparent"))
{
*rgba = (GdkRGBA) { 0, 0, 0, 0 };
}
else if (gdk_rgba_parse (rgba, token->string.string))
{
/* everything's fine */
}
else
{
gtk_css_parser_error_syntax (parser, "\"%s\" is not a valid color name.", token->string.string);
return FALSE;
}
gtk_css_parser_consume_token (parser);
return TRUE;
}
else
{
gtk_css_parser_error_syntax (parser, "Expected a valid color.");
return FALSE;
}
}
+33
View File
@@ -0,0 +1,33 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2010, Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_RGBA_PRIVATE_H__
#define __GDK_RGBA_PRIVATE_H__
#include "gdkrgba.h"
#include <gtk/css/gtkcss.h>
#include "gtk/css/gtkcssparserprivate.h"
gboolean gdk_rgba_parser_parse (GtkCssParser *parser,
GdkRGBA *rgba);
G_END_DECLS
#endif
+1 -1
View File
@@ -15,7 +15,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
#if !defined (__GDK_H_INSIDE__) && !defined (__GTK_CSS_H_INSIDE__) && !defined (GDK_COMPILATION) && !defined (GTK_CSS_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
+4
View File
@@ -194,6 +194,10 @@ gdk_vulkan_strerror (VkResult result)
case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
return "Invalid DRM format modifier plane layout";
#endif
#if VK_HEADER_VERSION >= 97
case VK_ERROR_INVALID_DEVICE_ADDRESS_EXT:
return "Invalid device address";
#endif
case VK_RESULT_RANGE_SIZE:
case VK_RESULT_MAX_ENUM:
+3 -2
View File
@@ -224,7 +224,8 @@ endif
# FIXME: might have to add '-xobjective-c' to c_args for quartz backend?
libgdk = static_library('gdk',
sources: [gdk_sources, gdk_backends_gen_headers, gdkconfig],
dependencies: gdk_deps,
dependencies: gdk_deps + [libgtk_css_dep],
link_with: [libgtk_css, ],
include_directories: [confinc, gdkx11_inc, wlinc],
c_args: [
'-DGDK_COMPILATION',
@@ -239,4 +240,4 @@ libgdk = static_library('gdk',
libgdk_dep = declare_dependency(
sources: ['gdk.h', gdkconfig, gdkenum_h],
include_directories: [confinc, gdkx11_inc, wlinc],
dependencies: gdk_deps)
dependencies: gdk_deps + [libgtk_css_dep])
+2 -2
View File
@@ -4318,10 +4318,10 @@ gsk_cross_fade_node_draw (GskRenderNode *node,
{
GskCrossFadeNode *self = (GskCrossFadeNode *) node;
cairo_push_group (cr);
cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
gsk_render_node_draw (self->start, cr);
cairo_push_group (cr);
cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
gsk_render_node_draw (self->end, cr);
cairo_pop_group_to_source (cr);
+257 -2
View File
@@ -1264,8 +1264,8 @@ gsk_transform_unref (GskTransform *self)
* @self: (allow-none): a #GskTransform
* @string: The string to print into
*
* Converts @self into a string representation suitable for printing that
* can later be parsed with gsk_transform_parse().
* Converts @self into a human-readable string representation suitable
* for printing that can later be parsed with gsk_transform_parse().
**/
void
gsk_transform_print (GskTransform *self,
@@ -1651,3 +1651,258 @@ gsk_transform_transform_bounds (GskTransform *self,
break;
}
}
static guint
gsk_transform_parse_float (GtkCssParser *parser,
guint n,
gpointer data)
{
float *f = data;
double d;
if (!gtk_css_parser_consume_number (parser, &d))
return 0;
f[n] = d;
return 1;
}
static guint
gsk_transform_parse_scale (GtkCssParser *parser,
guint n,
gpointer data)
{
float *f = data;
double d;
if (!gtk_css_parser_consume_number (parser, &d))
return 0;
f[n] = d;
f[1] = d;
return 1;
}
gboolean
gsk_transform_parser_parse (GtkCssParser *parser,
GskTransform **out_transform)
{
const GtkCssToken *token;
GskTransform *transform = NULL;
float f[16] = { 0, };
token = gtk_css_parser_get_token (parser);
if (gtk_css_token_is_ident (token, "none"))
{
gtk_css_parser_consume_token (parser);
*out_transform = NULL;
return TRUE;
}
while (TRUE)
{
if (gtk_css_token_is_function (token, "matrix"))
{
graphene_matrix_t matrix;
if (!gtk_css_parser_consume_function (parser, 6, 6, gsk_transform_parse_float, f))
goto fail;
graphene_matrix_init_from_2d (&matrix, f[0], f[1], f[2], f[3], f[4], f[5]);
transform = gsk_transform_matrix_with_category (transform,
&matrix,
GSK_TRANSFORM_CATEGORY_2D);
}
else if (gtk_css_token_is_function (token, "matrix3d"))
{
graphene_matrix_t matrix;
if (!gtk_css_parser_consume_function (parser, 16, 16, gsk_transform_parse_float, f))
goto fail;
graphene_matrix_init_from_float (&matrix, f);
transform = gsk_transform_matrix (transform, &matrix);
}
else if (gtk_css_token_is_function (token, "perspective"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_perspective (transform, f[0]);
}
else if (gtk_css_token_is_function (token, "rotate") ||
gtk_css_token_is_function (token, "rotateZ"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_rotate (transform, f[0]);
}
else if (gtk_css_token_is_function (token, "rotate3d"))
{
graphene_vec3_t axis;
if (!gtk_css_parser_consume_function (parser, 4, 4, gsk_transform_parse_float, f))
goto fail;
graphene_vec3_init (&axis, f[0], f[1], f[2]);
transform = gsk_transform_rotate_3d (transform, f[3], &axis);
}
else if (gtk_css_token_is_function (token, "rotateX"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_rotate_3d (transform, f[0], graphene_vec3_x_axis ());
}
else if (gtk_css_token_is_function (token, "rotateY"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_rotate_3d (transform, f[0], graphene_vec3_y_axis ());
}
else if (gtk_css_token_is_function (token, "scale"))
{
if (!gtk_css_parser_consume_function (parser, 1, 2, gsk_transform_parse_scale, f))
goto fail;
transform = gsk_transform_scale (transform, f[0], f[1]);
}
else if (gtk_css_token_is_function (token, "scale3d"))
{
if (!gtk_css_parser_consume_function (parser, 3, 3, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_scale_3d (transform, f[0], f[1], f[2]);
}
else if (gtk_css_token_is_function (token, "scaleX"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_scale (transform, f[0], 1.f);
}
else if (gtk_css_token_is_function (token, "scaleY"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_scale (transform, 1.f, f[0]);
}
else if (gtk_css_token_is_function (token, "scaleZ"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_scale_3d (transform, 1.f, 1.f, f[0]);
}
else if (gtk_css_token_is_function (token, "translate"))
{
f[1] = 0.f;
if (!gtk_css_parser_consume_function (parser, 1, 2, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (f[0], f[1]));
}
else if (gtk_css_token_is_function (token, "translate3d"))
{
if (!gtk_css_parser_consume_function (parser, 3, 3, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_translate_3d (transform, &GRAPHENE_POINT3D_INIT (f[0], f[1], f[2]));
}
else if (gtk_css_token_is_function (token, "translateX"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (f[0], 0.f));
}
else if (gtk_css_token_is_function (token, "translateY"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (0.f, f[0]));
}
else if (gtk_css_token_is_function (token, "translateZ"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gsk_transform_parse_float, f))
goto fail;
transform = gsk_transform_translate_3d (transform, &GRAPHENE_POINT3D_INIT (0.f, 0.f, f[0]));
}
#if 0
/* FIXME: add these */
else if (gtk_css_token_is_function (token, "skew"))
{
}
else if (gtk_css_token_is_function (token, "skewX"))
{
}
else if (gtk_css_token_is_function (token, "skewY"))
{
}
#endif
else
{
break;
}
token = gtk_css_parser_get_token (parser);
}
if (transform == NULL)
{
gtk_css_parser_error_syntax (parser, "Expected a transform");
goto fail;
}
*out_transform = transform;
return TRUE;
fail:
gsk_transform_unref (transform);
*out_transform = NULL;
return FALSE;
}
/**
* gsk_transform_parse:
* @string: the string to parse
* @out_transform: (out): The location to put the transform in
*
* Parses the given @string into a transform and puts it in
* @out_transform. Strings printed via gsk_transform_to_string()
* can be read in again successfully using this function.
*
* If @string does not describe a valid transform, %FALSE is
* returned and %NULL is put in @out_transform.
*
* Returns: %TRUE if @string described a valid transform.
**/
gboolean
gsk_transform_parse (const char *string,
GskTransform **out_transform)
{
GtkCssParser *parser;
GBytes *bytes;
gboolean result;
g_return_val_if_fail (string != NULL, FALSE);
g_return_val_if_fail (out_transform != NULL, FALSE);
bytes = g_bytes_new_static (string, strlen (string));
parser = gtk_css_parser_new_for_bytes (bytes, NULL, NULL, NULL, NULL, NULL);
result = gsk_transform_parser_parse (parser, out_transform);
if (result && !gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF))
{
g_clear_pointer (out_transform, gsk_transform_unref);
result = FALSE;
}
gtk_css_parser_unref (parser);
g_bytes_unref (bytes);
return result;
}
+3
View File
@@ -46,6 +46,9 @@ void gsk_transform_print (GskTransform
GDK_AVAILABLE_IN_ALL
char * gsk_transform_to_string (GskTransform *self);
GDK_AVAILABLE_IN_ALL
gboolean gsk_transform_parse (const char *string,
GskTransform **out_transform);
GDK_AVAILABLE_IN_ALL
void gsk_transform_to_matrix (GskTransform *self,
graphene_matrix_t *out_matrix);
GDK_AVAILABLE_IN_ALL
+7 -1
View File
@@ -23,15 +23,21 @@
#include "gsktransform.h"
#include <gsk/gsk.h>
#include "gsk/gskrendernodeprivate.h"
#include <gtk/css/gtkcss.h>
#include "gtk/css/gtkcssparserprivate.h"
G_BEGIN_DECLS
GskTransform * gsk_transform_matrix_with_category (GskTransform *next,
const graphene_matrix_t*matrix,
GskTransformCategory category);
gboolean gsk_transform_parser_parse (GtkCssParser *parser,
GskTransform **out_transform);
G_END_DECLS
#endif /* __GSK_TRANSFORM_PRIVATE_H__ */
+41
View File
@@ -0,0 +1,41 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GTK_CSS_H__
#define __GTK_CSS_H__
#define __GTK_CSS_H_INSIDE__
#include <glib.h>
#include <gdk/gdkversionmacros.h>
#include <gtk/css/gtkcssenums.h>
#include <gtk/css/gtkcssenumtypes.h>
#include <gtk/css/gtkcsserror.h>
#include <gtk/css/gtkcsslocation.h>
#include <gtk/css/gtkcsssection.h>
#undef __GTK_CSS_H_INSIDE__
#endif /* __GTK_CSS_H__ */
+77
View File
@@ -0,0 +1,77 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GTK_CSS_ENUMS_H__
#define __GTK_CSS_ENUMS_H__
#if !defined (__GTK_CSS_H_INSIDE__) && !defined (GTK_CSS_COMPILATION)
#error "Only <gtk/css/gtkcss.h> can be included directly."
#endif
#include <glib.h>
#include <gdk/gdkversionmacros.h>
/**
* GtkCssParserError:
* @GTK_CSS_PARSER_ERROR_FAILED: Unknown failure.
* @GTK_CSS_PARSER_ERROR_SYNTAX: The given text does not form valid
* syntax
* @GTK_CSS_PARSER_ERROR_IMPORT: Failed to import a resource
* @GTK_CSS_PARSER_ERROR_NAME: The given name has not been defined
* @GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE: The given value is not
* correct
*
* Errors that can occur while parsing CSS.
*
* These errors are unexpected and will cause parts of the given CSS
* to be ignored.
*/
typedef enum
{
GTK_CSS_PARSER_ERROR_FAILED,
GTK_CSS_PARSER_ERROR_SYNTAX,
GTK_CSS_PARSER_ERROR_IMPORT,
GTK_CSS_PARSER_ERROR_NAME,
GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE
} GtkCssParserError;
/**
* GtkCssParserWarning:
* @GTK_CSS_PARSER_WARNING_DEPRECATED: The given construct is
* deprecated and will be removed in a future version
* @GTK_CSS_PARSER_WARNING_SYNTAX: A syntax construct was used
* that should be avoided
*
* Warnings that can occur while parsing CSS.
*
* Unlike #GtkCssParserErrors, warnings do not cause the parser to
* skip any input, but they indicate issues that should be fixed.
*/
typedef enum
{
GTK_CSS_PARSER_WARNING_DEPRECATED,
GTK_CSS_PARSER_WARNING_SYNTAX
} GtkCssParserWarning;
#endif /* __GTK_CSS_ENUMS_H__ */
+38
View File
@@ -0,0 +1,38 @@
/*** BEGIN file-header ***/
#include "config.h"
#include "gtkcssenumtypes.h"
#include <gtkcss.h>
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@basename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType
@enum_name@_get_type (void)
{
static volatile gsize g_define_type_id__volatile = 0;
if (g_once_init_enter (&g_define_type_id__volatile))
{
static const G@Type@Value values[] = {
/*** END value-header ***/
/*** BEGIN value-production ***/
{ @VALUENAME@, "@VALUENAME@", "@valuenick@" },
/*** END value-production ***/
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
GType g_define_type_id =
g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
}
return g_define_type_id__volatile;
}
/*** END value-tail ***/
+29
View File
@@ -0,0 +1,29 @@
/*** BEGIN file-header ***/
#ifndef __GTK_CSS_ENUM_TYPES_H__
#define __GTK_CSS_ENUM_TYPES_H__
#if !defined (__GTK_CSS_H_INSIDE__) && !defined (GTK_CSS_COMPILATION)
#error "Only <gtk/css/gtkcss.h> can be included directly."
#endif
#include <glib-object.h>
#include <gdk/gdkversionmacros.h>
G_BEGIN_DECLS
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@basename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GDK_AVAILABLE_IN_ALL GType @enum_name@_get_type (void) G_GNUC_CONST;
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
/*** END value-header ***/
/*** BEGIN file-tail ***/
G_END_DECLS
#endif /* __GTK_CSS_ENUM_TYPES_H__ */
/*** END file-tail ***/
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright © 2019 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkcsserror.h"
GQuark
gtk_css_parser_error_quark (void)
{
return g_quark_from_static_string ("gtk-css-parser-error-quark");
}
GQuark
gtk_css_parser_warning_quark (void)
{
return g_quark_from_static_string ("gtk-css-parser-warning-quark");
}
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright © 2019 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_ERROR_H__
#define __GTK_CSS_ERROR_H__
#include <glib.h>
#include <gdk/gdkversionmacros.h>
/**
* GTK_CSS_PARSER_ERROR:
*
* Domain for #GtkCssParser errors.
*/
#define GTK_CSS_PARSER_ERROR (gtk_css_parser_error_quark ())
GDK_AVAILABLE_IN_ALL
GQuark gtk_css_parser_error_quark (void);
/**
* GTK_CSS_PARSER_WARNING:
*
* Domain for #GtkCssParser warnings.
*/
#define GTK_CSS_PARSER_WARNING (gtk_css_parser_warning_quark ())
GDK_AVAILABLE_IN_ALL
GQuark gtk_css_parser_warning_quark (void);
#endif /* __GTK_CSS_ERROR_H__ */
+74
View File
@@ -0,0 +1,74 @@
/* GSK - The GIMP Toolkit
* Copyright (C) 2019 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkcsslocationprivate.h"
/**
* GtkCssLocation:
* @bytes: number of bytes parsed since the beginning
* @chars: number of characters parsed since the beginning
* @lines: number of full lines that have been parsed
* If you want to display this as a line number, you
* need to add 1 to this.
* @line_bytes: Number of bytes parsed since the last line break
* @line_chars: Number of characters parsed since the last line
* break
*
* @GtkCssLocation is used to present a location in a file - or other
* source of data parsed by the CSS engine.
*
* The @bytes and @line_bytes offsets are meant to be used to
* programmatically match data. The @lines and @line_chars offsets
* can be used for printing the location in a file.
*
* Note that the @lines parameter starts from 0 and is increased
* whenever a CSS line break is encountered. (CSS defines the C character
* sequences "\r\n", "\r", "\n" and "\f" as newlines.)
* If your document uses different rules for line breaking, you might want
* run into problems here.
*/
void
gtk_css_location_init (GtkCssLocation *location)
{
memset (location, 0, sizeof (GtkCssLocation));
}
void
gtk_css_location_advance (GtkCssLocation *location,
gsize bytes,
gsize chars)
{
location->bytes += bytes;
location->chars += chars;
location->line_bytes += bytes;
location->line_chars += chars;
}
void
gtk_css_location_advance_newline (GtkCssLocation *location,
gboolean is_windows)
{
gtk_css_location_advance (location, is_windows ? 2 : 1, is_windows ? 2 : 1);
location->lines++;
location->line_bytes = 0;
location->line_chars = 0;
}
+43
View File
@@ -0,0 +1,43 @@
/* GSK - The GIMP Toolkit
* Copyright (C) 2011 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_CSS_LOCATION_H__
#define __GTK_CSS_LOCATION_H__
#if !defined (__GTK_CSS_H_INSIDE__) && !defined (GTK_CSS_COMPILATION)
#error "Only <gtk/css/gtkcss.h> can be included directly."
#endif
#include <glib.h>
G_BEGIN_DECLS
typedef struct _GtkCssLocation GtkCssLocation;
struct _GtkCssLocation
{
gsize bytes;
gsize chars;
gsize lines;
gsize line_bytes;
gsize line_chars;
};
G_END_DECLS
#endif /* __GTK_CSS_LOCATION_H__ */
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright © 2019 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_LOCATION_PRIVATE_H__
#define __GTK_CSS_LOCATION_PRIVATE_H__
#include "gtkcsslocation.h"
G_BEGIN_DECLS
void gtk_css_location_init (GtkCssLocation *location);
void gtk_css_location_advance (GtkCssLocation *location,
gsize bytes,
gsize chars);
void gtk_css_location_advance_newline (GtkCssLocation *location,
gboolean is_windows);
G_END_DECLS
#endif /* __GTK_CSS_LOCATION_PRIVATE_H__ */
File diff suppressed because it is too large Load Diff
+155
View File
@@ -0,0 +1,155 @@
/*
* Copyright © 2019 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_PARSER_H__
#define __GTK_CSS_PARSER_H__
#include "gtkcssenums.h"
#include "gtkcsstokenizerprivate.h"
#include <gio/gio.h>
G_BEGIN_DECLS
typedef struct _GtkCssParser GtkCssParser;
typedef struct _GtkCssParseOption GtkCssParseOption;
struct _GtkCssParseOption
{
gboolean (* can_parse) (GtkCssParser *parser,
gpointer option_data,
gpointer user_data);
gboolean (* parse) (GtkCssParser *parser,
gpointer option_data,
gpointer user_data);
gpointer data;
};
typedef void (* GtkCssParserErrorFunc) (GtkCssParser *parser,
const GtkCssLocation *start,
const GtkCssLocation *end,
const GError *error,
gpointer user_data);
GtkCssParser * gtk_css_parser_new_for_file (GFile *file,
GtkCssParserErrorFunc error_func,
gpointer user_data,
GDestroyNotify user_destroy,
GError **error);
GtkCssParser * gtk_css_parser_new_for_bytes (GBytes *bytes,
GFile *file,
GFile *base_directory,
GtkCssParserErrorFunc error_func,
gpointer user_data,
GDestroyNotify user_destroy);
GtkCssParser * gtk_css_parser_ref (GtkCssParser *self);
void gtk_css_parser_unref (GtkCssParser *self);
GFile * gtk_css_parser_get_file (GtkCssParser *self);
GFile * gtk_css_parser_resolve_url (GtkCssParser *self,
const char *url);
const GtkCssLocation * gtk_css_parser_get_start_location (GtkCssParser *self);
const GtkCssLocation * gtk_css_parser_get_end_location (GtkCssParser *self);
const GtkCssLocation * gtk_css_parser_get_block_location (GtkCssParser *self);
const GtkCssToken * gtk_css_parser_peek_token (GtkCssParser *self);
const GtkCssToken * gtk_css_parser_get_token (GtkCssParser *self);
void gtk_css_parser_consume_token (GtkCssParser *self);
void gtk_css_parser_start_block (GtkCssParser *self);
void gtk_css_parser_start_semicolon_block (GtkCssParser *self,
GtkCssTokenType alternative_token);
void gtk_css_parser_end_block_prelude (GtkCssParser *self);
void gtk_css_parser_end_block (GtkCssParser *self);
void gtk_css_parser_skip (GtkCssParser *self);
void gtk_css_parser_skip_until (GtkCssParser *self,
GtkCssTokenType token_type);
void gtk_css_parser_emit_error (GtkCssParser *self,
const GtkCssLocation *start,
const GtkCssLocation *end,
const GError *error);
void gtk_css_parser_error (GtkCssParser *self,
GtkCssParserError code,
const GtkCssLocation *start,
const GtkCssLocation *end,
const char *format,
...) G_GNUC_PRINTF(5, 6);
void gtk_css_parser_error_syntax (GtkCssParser *self,
const char *format,
...) G_GNUC_PRINTF(2, 3);
void gtk_css_parser_error_value (GtkCssParser *self,
const char *format,
...) G_GNUC_PRINTF(2, 3);
void gtk_css_parser_error_import (GtkCssParser *self,
const char *format,
...) G_GNUC_PRINTF(2, 3);
void gtk_css_parser_warn (GtkCssParser *self,
GtkCssParserWarning code,
const GtkCssLocation *start,
const GtkCssLocation *end,
const char *format,
...) G_GNUC_PRINTF(5, 6);
void gtk_css_parser_warn_syntax (GtkCssParser *self,
const char *format,
...) G_GNUC_PRINTF(2, 3);
gboolean gtk_css_parser_has_token (GtkCssParser *self,
GtkCssTokenType token_type);
gboolean gtk_css_parser_has_ident (GtkCssParser *self,
const char *ident);
gboolean gtk_css_parser_has_integer (GtkCssParser *self);
gboolean gtk_css_parser_has_function (GtkCssParser *self,
const char *name);
gboolean gtk_css_parser_try_delim (GtkCssParser *self,
gunichar codepoint);
gboolean gtk_css_parser_try_ident (GtkCssParser *self,
const char *ident);
gboolean gtk_css_parser_try_at_keyword (GtkCssParser *self,
const char *keyword);
gboolean gtk_css_parser_try_token (GtkCssParser *self,
GtkCssTokenType token_type);
char * gtk_css_parser_consume_ident (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT;
char * gtk_css_parser_consume_string (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT;
GFile * gtk_css_parser_consume_url (GtkCssParser *self) G_GNUC_WARN_UNUSED_RESULT;
gboolean gtk_css_parser_consume_number (GtkCssParser *self,
double *number);
gboolean gtk_css_parser_consume_integer (GtkCssParser *self,
int *number);
gboolean gtk_css_parser_consume_percentage (GtkCssParser *self,
double *number);
gboolean gtk_css_parser_consume_function (GtkCssParser *self,
guint min_args,
guint max_args,
guint (* parse_func) (GtkCssParser *, guint, gpointer),
gpointer data);
gsize gtk_css_parser_consume_any (GtkCssParser *parser,
const GtkCssParseOption *options,
gsize n_options,
gpointer user_data);
G_END_DECLS
#endif /* __GTK_CSS_PARSER_H__ */
+253
View File
@@ -0,0 +1,253 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkcsssection.h"
#include "gtkcssparserprivate.h"
struct _GtkCssSection
{
gint ref_count;
GtkCssSection *parent;
GFile *file;
GtkCssLocation start_location;
GtkCssLocation end_location; /* end location if parser is %NULL */
};
G_DEFINE_BOXED_TYPE (GtkCssSection, gtk_css_section, gtk_css_section_ref, gtk_css_section_unref)
/**
* gtk_css_section_new: (constructor)
* @file: (nullable) (transfer none): The file this section refers to
* @start: The start location
* @end: The end location
*
* Creates a new #GtkCssSection referring to the section
* in the given @file from the @start location to the
* @end location.
*
* Returns: a new #GtkCssSection
**/
GtkCssSection *
gtk_css_section_new (GFile *file,
const GtkCssLocation *start,
const GtkCssLocation *end)
{
GtkCssSection *result;
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
g_return_val_if_fail (start != NULL, NULL);
g_return_val_if_fail (end != NULL, NULL);
result = g_slice_new0 (GtkCssSection);
result->ref_count = 1;
if (file)
result->file = g_object_ref (file);
result->start_location = *start;
result->end_location = *end;
return result;
}
/**
* gtk_css_section_ref:
* @section: a #GtkCssSection
*
* Increments the reference count on @section.
*
* Returns: @section itself.
**/
GtkCssSection *
gtk_css_section_ref (GtkCssSection *section)
{
g_return_val_if_fail (section != NULL, NULL);
section->ref_count += 1;
return section;
}
/**
* gtk_css_section_unref:
* @section: a #GtkCssSection
*
* Decrements the reference count on @section, freeing the
* structure if the reference count reaches 0.
**/
void
gtk_css_section_unref (GtkCssSection *section)
{
g_return_if_fail (section != NULL);
section->ref_count -= 1;
if (section->ref_count > 0)
return;
if (section->parent)
gtk_css_section_unref (section->parent);
if (section->file)
g_object_unref (section->file);
g_slice_free (GtkCssSection, section);
}
/**
* gtk_css_section_get_parent:
* @section: the section
*
* Gets the parent section for the given @section. The parent section is
* the section that contains this @section. A special case are sections of
* type #GTK_CSS_SECTION_DOCUMENT. Their parent will either be %NULL
* if they are the original CSS document that was loaded by
* gtk_css_provider_load_from_file() or a section of type
* #GTK_CSS_SECTION_IMPORT if it was loaded with an import rule from
* a different file.
*
* Returns: (nullable) (transfer none): the parent section or %NULL if none
**/
GtkCssSection *
gtk_css_section_get_parent (const GtkCssSection *section)
{
g_return_val_if_fail (section != NULL, NULL);
return section->parent;
}
/**
* gtk_css_section_get_file:
* @section: the section
*
* Gets the file that @section was parsed from. If no such file exists,
* for example because the CSS was loaded via
* @gtk_css_provider_load_from_data(), then %NULL is returned.
*
* Returns: (transfer none): the #GFile that @section was parsed from
* or %NULL if @section was parsed from other data
**/
GFile *
gtk_css_section_get_file (const GtkCssSection *section)
{
g_return_val_if_fail (section != NULL, NULL);
return section->file;
}
/**
* gtk_css_section_get_start_location:
* @section: the section
*
* Returns the location in the CSS document where this section starts.
*
* Returns: (tranfer none) (not nullable): The start location of
* this section
**/
const GtkCssLocation *
gtk_css_section_get_start_location (const GtkCssSection *section)
{
g_return_val_if_fail (section != NULL, NULL);
return &section->start_location;
}
/**
* gtk_css_section_get_end_location:
* @section: the section
*
* Returns the location in the CSS document where this section ends.
*
* Returns: (tranfer none) (not nullable): The end location of
* this section
**/
const GtkCssLocation *
gtk_css_section_get_end_location (const GtkCssSection *section)
{
g_return_val_if_fail (section != NULL, NULL);
return &section->end_location;
}
/**
* gtk_css_section_print:
* @section: a section
* @string: a #GString to print to
*
* Prints the @section into @string in a human-readable form. This
* is a form like `gtk.css:32:1-23` to denote line 32, characters
* 1 to 23 in the file gtk.css.
**/
void
gtk_css_section_print (const GtkCssSection *section,
GString *string)
{
if (section->file)
{
GFileInfo *info;
info = g_file_query_info (section->file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, 0, NULL, NULL);
if (info)
{
g_string_append (string, g_file_info_get_display_name (info));
g_object_unref (info);
}
else
{
g_string_append (string, "<broken file>");
}
}
else
{
g_string_append (string, "<data>");
}
g_string_append_printf (string, ":%zu:%zu",
section->start_location.lines + 1,
section->start_location.line_chars + 1);
if (section->start_location.lines != section->end_location.lines ||
section->start_location.line_chars != section->end_location.line_chars)
{
g_string_append (string, "-");
if (section->start_location.lines != section->end_location.lines)
g_string_append_printf (string, "%zu:", section->end_location.lines + 1);
g_string_append_printf (string, "%zu", section->end_location.line_chars + 1);
}
}
/**
* gtk_css_section_to_string:
* @section: a #GtkCssSection
*
* Prints the section into a human-readable text form using
* gtk_css_section_print().
*
* Returns: (transfer full): A new string.
**/
char *
gtk_css_section_to_string (const GtkCssSection *section)
{
GString *string;
g_return_val_if_fail (section != NULL, NULL);
string = g_string_new (NULL);
gtk_css_section_print (section, string);
return g_string_free (string, FALSE);
}
+19 -44
View File
@@ -18,49 +18,18 @@
#ifndef __GTK_CSS_SECTION_H__
#define __GTK_CSS_SECTION_H__
#if !defined (__GTK_CSS_H_INSIDE__) && !defined (GTK_CSS_COMPILATION)
#error "Only <gtk/css/gtkcss.h> can be included directly."
#endif
#include <gio/gio.h>
#include <gdk/gdk.h>
#include <gdk/gdkversionmacros.h>
#include <gtk/css/gtkcsslocation.h>
G_BEGIN_DECLS
#define GTK_TYPE_CSS_SECTION (gtk_css_section_get_type ())
/**
* GtkCssSectionType:
* @GTK_CSS_SECTION_DOCUMENT: The section describes a complete document.
* This section time is the only one where gtk_css_section_get_parent()
* might return %NULL.
* @GTK_CSS_SECTION_IMPORT: The section defines an import rule.
* @GTK_CSS_SECTION_COLOR_DEFINITION: The section defines a color. This
* is a GTK extension to CSS.
* @GTK_CSS_SECTION_RULESET: The section defines a CSS ruleset.
* @GTK_CSS_SECTION_SELECTOR: The section defines a CSS selector.
* @GTK_CSS_SECTION_DECLARATION: The section defines the declaration of
* a CSS variable.
* @GTK_CSS_SECTION_VALUE: The section defines the value of a CSS declaration.
* @GTK_CSS_SECTION_KEYFRAMES: The section defines keyframes. See [CSS
* Animations](http://dev.w3.org/csswg/css3-animations/#keyframes) for details
*
* The different types of sections indicate parts of a CSS document as
* parsed by GTKs CSS parser. They are oriented towards the
* [CSS Grammar](http://www.w3.org/TR/CSS21/grammar.html),
* but may contain extensions.
*
* More types might be added in the future as the parser incorporates
* more features.
*/
typedef enum
{
GTK_CSS_SECTION_DOCUMENT,
GTK_CSS_SECTION_IMPORT,
GTK_CSS_SECTION_COLOR_DEFINITION,
GTK_CSS_SECTION_RULESET,
GTK_CSS_SECTION_SELECTOR,
GTK_CSS_SECTION_DECLARATION,
GTK_CSS_SECTION_VALUE,
GTK_CSS_SECTION_KEYFRAMES
} GtkCssSectionType;
/**
* GtkCssSection:
*
@@ -73,25 +42,31 @@ typedef struct _GtkCssSection GtkCssSection;
GDK_AVAILABLE_IN_ALL
GType gtk_css_section_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkCssSection * gtk_css_section_new (GFile *file,
const GtkCssLocation *start,
const GtkCssLocation *end);
GDK_AVAILABLE_IN_ALL
GtkCssSection * gtk_css_section_ref (GtkCssSection *section);
GDK_AVAILABLE_IN_ALL
void gtk_css_section_unref (GtkCssSection *section);
GDK_AVAILABLE_IN_ALL
GtkCssSectionType gtk_css_section_get_section_type (const GtkCssSection *section);
void gtk_css_section_print (const GtkCssSection *section,
GString *string);
GDK_AVAILABLE_IN_ALL
char * gtk_css_section_to_string (const GtkCssSection *section);
GDK_AVAILABLE_IN_ALL
GtkCssSection * gtk_css_section_get_parent (const GtkCssSection *section);
GDK_AVAILABLE_IN_ALL
GFile * gtk_css_section_get_file (const GtkCssSection *section);
GDK_AVAILABLE_IN_ALL
guint gtk_css_section_get_start_line (const GtkCssSection *section);
const GtkCssLocation *
gtk_css_section_get_start_location (const GtkCssSection *section);
GDK_AVAILABLE_IN_ALL
guint gtk_css_section_get_start_position (const GtkCssSection *section);
GDK_AVAILABLE_IN_ALL
guint gtk_css_section_get_end_line (const GtkCssSection *section);
GDK_AVAILABLE_IN_ALL
guint gtk_css_section_get_end_position (const GtkCssSection *section);
const GtkCssLocation *
gtk_css_section_get_end_location (const GtkCssSection *section);
G_END_DECLS
File diff suppressed because it is too large Load Diff
+140
View File
@@ -0,0 +1,140 @@
/* GSK - The GIMP Toolkit
* Copyright (C) 2011 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_CSS_TOKENIZER_PRIVATE_H__
#define __GTK_CSS_TOKENIZER_PRIVATE_H__
#include <glib.h>
#include <gtk/css/gtkcsslocation.h>
G_BEGIN_DECLS
typedef enum {
/* no content */
GTK_CSS_TOKEN_EOF,
GTK_CSS_TOKEN_WHITESPACE,
GTK_CSS_TOKEN_OPEN_PARENS,
GTK_CSS_TOKEN_CLOSE_PARENS,
GTK_CSS_TOKEN_OPEN_SQUARE,
GTK_CSS_TOKEN_CLOSE_SQUARE,
GTK_CSS_TOKEN_OPEN_CURLY,
GTK_CSS_TOKEN_CLOSE_CURLY,
GTK_CSS_TOKEN_COMMA,
GTK_CSS_TOKEN_COLON,
GTK_CSS_TOKEN_SEMICOLON,
GTK_CSS_TOKEN_CDO,
GTK_CSS_TOKEN_CDC,
GTK_CSS_TOKEN_INCLUDE_MATCH,
GTK_CSS_TOKEN_DASH_MATCH,
GTK_CSS_TOKEN_PREFIX_MATCH,
GTK_CSS_TOKEN_SUFFIX_MATCH,
GTK_CSS_TOKEN_SUBSTRING_MATCH,
GTK_CSS_TOKEN_COLUMN,
GTK_CSS_TOKEN_BAD_STRING,
GTK_CSS_TOKEN_BAD_URL,
GTK_CSS_TOKEN_COMMENT,
/* delim */
GTK_CSS_TOKEN_DELIM,
/* string */
GTK_CSS_TOKEN_STRING,
GTK_CSS_TOKEN_IDENT,
GTK_CSS_TOKEN_FUNCTION,
GTK_CSS_TOKEN_AT_KEYWORD,
GTK_CSS_TOKEN_HASH_UNRESTRICTED,
GTK_CSS_TOKEN_HASH_ID,
GTK_CSS_TOKEN_URL,
/* number */
GTK_CSS_TOKEN_SIGNED_INTEGER,
GTK_CSS_TOKEN_SIGNLESS_INTEGER,
GTK_CSS_TOKEN_SIGNED_NUMBER,
GTK_CSS_TOKEN_SIGNLESS_NUMBER,
GTK_CSS_TOKEN_PERCENTAGE,
/* dimension */
GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION,
GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION,
GTK_CSS_TOKEN_DIMENSION
} GtkCssTokenType;
typedef union _GtkCssToken GtkCssToken;
typedef struct _GtkCssTokenizer GtkCssTokenizer;
typedef struct _GtkCssStringToken GtkCssStringToken;
typedef struct _GtkCssDelimToken GtkCssDelimToken;
typedef struct _GtkCssNumberToken GtkCssNumberToken;
typedef struct _GtkCssDimensionToken GtkCssDimensionToken;
struct _GtkCssStringToken {
GtkCssTokenType type;
char *string;
};
struct _GtkCssDelimToken {
GtkCssTokenType type;
gunichar delim;
};
struct _GtkCssNumberToken {
GtkCssTokenType type;
double number;
};
struct _GtkCssDimensionToken {
GtkCssTokenType type;
double value;
char *dimension;
};
union _GtkCssToken {
GtkCssTokenType type;
GtkCssStringToken string;
GtkCssDelimToken delim;
GtkCssNumberToken number;
GtkCssDimensionToken dimension;
};
void gtk_css_token_clear (GtkCssToken *token);
gboolean gtk_css_token_is_finite (const GtkCssToken *token);
gboolean gtk_css_token_is_preserved (const GtkCssToken *token,
GtkCssTokenType *out_closing);
#define gtk_css_token_is(token, _type) ((token)->type == (_type))
gboolean gtk_css_token_is_ident (const GtkCssToken *token,
const char *ident);
gboolean gtk_css_token_is_function (const GtkCssToken *token,
const char *ident);
gboolean gtk_css_token_is_delim (const GtkCssToken *token,
gunichar delim);
void gtk_css_token_print (const GtkCssToken *token,
GString *string);
char * gtk_css_token_to_string (const GtkCssToken *token);
GtkCssTokenizer * gtk_css_tokenizer_new (GBytes *bytes);
GtkCssTokenizer * gtk_css_tokenizer_ref (GtkCssTokenizer *tokenizer);
void gtk_css_tokenizer_unref (GtkCssTokenizer *tokenizer);
const GtkCssLocation * gtk_css_tokenizer_get_location (GtkCssTokenizer *tokenizer);
gboolean gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer,
GtkCssToken *token,
GError **error);
G_END_DECLS
#endif /* __GTK_CSS_TOKENIZER_PRIVATE_H__ */
+57
View File
@@ -0,0 +1,57 @@
gtk_css_public_sources = files([
'gtkcsslocation.c',
'gtkcsserror.c',
'gtkcsssection.c',
])
gtk_css_private_sources = files([
'gtkcssparser.c',
'gtkcsstokenizer.c',
])
gtk_css_public_headers = files([
'gtkcssenums.h',
'gtkcsserror.h',
'gtkcsslocation.h',
'gtkcsssection.h',
])
install_headers(gtk_css_public_headers, 'gtkcss.h', subdir: 'gtk-4.0/gtk/css')
gtk_css_deps = [
libm,
glib_dep,
gobject_dep,
platform_gio_dep,
]
gtk_css_enums = gnome.mkenums('gtkcssenumtypes',
sources: gtk_css_public_headers,
c_template: 'gtkcssenumtypes.c.template',
h_template: 'gtkcssenumtypes.h.template',
install_dir: join_paths(gtk_includedir, 'gtk-4.0/gtk/css'),
install_header: true)
gtk_css_enum_h = gtk_css_enums[1]
libgtk_css = static_library('gtk_css',
sources: [
gtk_css_public_sources,
gtk_css_private_sources,
gtk_css_enums,
],
dependencies: gtk_css_deps,
include_directories: [ confinc, ],
c_args: [
'-DGTK_CSS_COMPILATION',
'-DG_LOG_DOMAIN="Gtk"',
'-DG_LOG_STRUCTURED=1',
] + common_cflags,
link_args: common_ldflags)
# We don't have link_with: to internal static libs here on purpose, just
# list the dependencies and generated headers and such, for use in the
# "public" libgtk_dep used by internal executables.
libgtk_css_dep = declare_dependency(include_directories: [ confinc, ],
sources: [ gtk_css_enum_h ],
dependencies: gtk_css_deps)
+3 -1
View File
@@ -27,7 +27,10 @@
#define __GTK_H_INSIDE__
#include <gtk/css/gtkcss.h>
#include <gdk/gdk.h>
#include <gsk/gsk.h>
#include <gtk/gtkaboutdialog.h>
#include <gtk/gtkaccelgroup.h>
#include <gtk/gtkaccellabel.h>
@@ -81,7 +84,6 @@
#include <gtk/gtkcomboboxtext.h>
#include <gtk/gtkcontainer.h>
#include <gtk/gtkcssprovider.h>
#include <gtk/gtkcsssection.h>
#include <gtk/gtkcustomlayout.h>
#include <gtk/gtkdebug.h>
#include <gtk/gtkdialog.h>
-12
View File
@@ -199,17 +199,6 @@ get_spacing (GtkBoxLayout *self,
return css_spacing + self->spacing;
}
static GtkSizeRequestMode
gtk_box_layout_get_request_mode (GtkLayoutManager *layout_manager,
GtkWidget *widget)
{
GtkBoxLayout *self = GTK_BOX_LAYOUT (layout_manager);
return self->orientation == GTK_ORIENTATION_HORIZONTAL
? GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT
: GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
}
static void
gtk_box_layout_compute_size (GtkBoxLayout *self,
GtkWidget *widget,
@@ -713,7 +702,6 @@ gtk_box_layout_class_init (GtkBoxLayoutClass *klass)
gobject_class->set_property = gtk_box_layout_set_property;
gobject_class->get_property = gtk_box_layout_get_property;
layout_manager_class->get_request_mode = gtk_box_layout_get_request_mode;
layout_manager_class->measure = gtk_box_layout_measure;
layout_manager_class->allocate = gtk_box_layout_allocate;
+16
View File
@@ -2061,6 +2061,22 @@ gtk_builder_value_from_string_type (GtkBuilder *builder,
ret = FALSE;
}
}
else if (G_VALUE_HOLDS (value, GSK_TYPE_TRANSFORM))
{
GskTransform *transform;
if (gsk_transform_parse (string, &transform))
g_value_take_boxed (value, transform);
else
{
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_VALUE,
"Could not parse transform '%s'",
string);
ret = FALSE;
}
}
else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
{
gchar **vector = g_strsplit (string, "\n", 0);
+1
View File
@@ -391,6 +391,7 @@ create_icon_helper (
icon_helper = gtk_icon_helper_new (gtk_style_context_get_node (gtk_widget_get_style_context (widget)),
widget);
_gtk_icon_helper_set_use_fallback (icon_helper, TRUE);
_gtk_icon_helper_set_force_scale_pixbuf (icon_helper, TRUE);
_gtk_icon_helper_set_definition (icon_helper, priv->image_def);
+11 -2
View File
@@ -835,14 +835,23 @@ gtk_compose_table_list_add_array (GSList *compose_tables,
{
guint32 hash;
GtkComposeTable *compose_table;
int n_index_stride = max_seq_len + 2;
int length = n_index_stride * n_seqs;
gsize n_index_stride;
gsize length;
gsize max_size = (gsize) -1;
int i;
guint16 *gtk_compose_seqs = NULL;
g_return_val_if_fail (data != NULL, compose_tables);
g_return_val_if_fail (max_seq_len <= GTK_MAX_COMPOSE_LEN, compose_tables);
n_index_stride = MIN (max_seq_len, GTK_MAX_COMPOSE_LEN) + 2;
if (n_seqs > max_size / n_index_stride)
{
g_critical ("Overflow in the compose sequences");
return compose_tables;
}
length = n_index_stride * n_seqs;
hash = gtk_compose_table_data_hash (data, length);
if (g_slist_find_custom (compose_tables, GINT_TO_POINTER (hash), gtk_compose_table_find) != NULL)
-1
View File
@@ -28,7 +28,6 @@
#include "gtkcssinheritvalueprivate.h"
#include "gtkcssinitialvalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcsssectionprivate.h"
#include "gtkcssshorthandpropertyprivate.h"
#include "gtkcssstaticstyleprivate.h"
#include "gtkcssstringvalueprivate.h"
+1 -1
View File
@@ -421,7 +421,7 @@ _gtk_css_array_value_parse (GtkCssParser *parser,
}
g_ptr_array_add (values, value);
} while (_gtk_css_parser_try (parser, ",", TRUE));
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
result = _gtk_css_array_value_new_from_array ((GtkCssValue **) values->pdata, values->len);
g_ptr_array_free (values, TRUE);
+4 -4
View File
@@ -187,12 +187,12 @@ _gtk_css_bg_size_value_parse (GtkCssParser *parser)
{
GtkCssValue *x, *y;
if (_gtk_css_parser_try (parser, "cover", TRUE))
if (gtk_css_parser_try_ident (parser, "cover"))
return _gtk_css_value_ref (&cover_singleton);
else if (_gtk_css_parser_try (parser, "contain", TRUE))
else if (gtk_css_parser_try_ident (parser, "contain"))
return _gtk_css_value_ref (&contain_singleton);
if (_gtk_css_parser_try (parser, "auto", TRUE))
if (gtk_css_parser_try_ident (parser, "auto"))
x = NULL;
else
{
@@ -204,7 +204,7 @@ _gtk_css_bg_size_value_parse (GtkCssParser *parser)
return NULL;
}
if (_gtk_css_parser_try (parser, "auto", TRUE))
if (gtk_css_parser_try_ident (parser, "auto"))
y = NULL;
else if (!gtk_css_number_value_can_parse (parser))
y = NULL;
+4 -4
View File
@@ -178,11 +178,11 @@ _gtk_css_border_value_parse (GtkCssParser *parser,
result = _gtk_css_border_value_new (NULL, NULL, NULL, NULL);
if (allow_fill)
result->fill = _gtk_css_parser_try (parser, "fill", TRUE);
result->fill = gtk_css_parser_try_ident (parser, "fill");
for (i = 0; i < 4; i++)
{
if (allow_auto && _gtk_css_parser_try (parser, "auto", TRUE))
if (allow_auto && gtk_css_parser_try_ident (parser, "auto"))
continue;
if (!gtk_css_number_value_can_parse (parser))
@@ -198,13 +198,13 @@ _gtk_css_border_value_parse (GtkCssParser *parser,
if (i == 0)
{
_gtk_css_parser_error (parser, "Expected a number");
gtk_css_parser_error_syntax (parser, "Expected a number");
_gtk_css_value_unref (result);
return NULL;
}
if (allow_fill && !result->fill)
result->fill = _gtk_css_parser_try (parser, "fill", TRUE);
result->fill = gtk_css_parser_try_ident (parser, "fill");
for (; i < 4; i++)
{
+65 -38
View File
@@ -316,25 +316,35 @@ static GtkCssValue *
gtk_css_calc_value_parse_value (GtkCssParser *parser,
GtkCssNumberParseFlags flags)
{
if (_gtk_css_parser_has_prefix (parser, "calc"))
if (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_OPEN_PARENS))
{
_gtk_css_parser_error (parser, "Nested calc() expressions are not allowed.");
return NULL;
}
GtkCssValue *result;
if (_gtk_css_parser_try (parser, "(", TRUE))
{
GtkCssValue *result = gtk_css_calc_value_parse_sum (parser, flags);
gtk_css_parser_start_block (parser);
result = gtk_css_calc_value_parse_sum (parser, flags);
if (result == NULL)
return NULL;
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_parser_error (parser, "Missing closing ')' in calc() subterm");
_gtk_css_value_unref (result);
gtk_css_parser_end_block (parser);
return NULL;
}
if (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF))
{
GtkCssLocation start = *gtk_css_parser_get_start_location (parser);
gtk_css_parser_skip_until (parser, GTK_CSS_TOKEN_EOF);
gtk_css_parser_error (parser,
GTK_CSS_PARSER_ERROR_SYNTAX,
&start,
gtk_css_parser_get_start_location (parser),
"Expected closing ')' in calc() subterm");
gtk_css_value_unref (result);
gtk_css_parser_end_block (parser);
return NULL;
}
gtk_css_parser_end_block (parser);
return result;
}
@@ -354,19 +364,21 @@ gtk_css_calc_value_parse_product (GtkCssParser *parser,
{
GtkCssValue *result, *value, *temp;
GtkCssNumberParseFlags actual_flags;
GtkCssLocation start;
actual_flags = flags | GTK_CSS_PARSE_NUMBER;
gtk_css_parser_get_token (parser);
start = *gtk_css_parser_get_start_location (parser);
result = gtk_css_calc_value_parse_value (parser, actual_flags);
if (result == NULL)
return NULL;
while (_gtk_css_parser_begins_with (parser, '*') || _gtk_css_parser_begins_with (parser, '/'))
while (TRUE)
{
if (actual_flags != GTK_CSS_PARSE_NUMBER && !is_number (result))
actual_flags = GTK_CSS_PARSE_NUMBER;
if (_gtk_css_parser_try (parser, "*", TRUE))
if (gtk_css_parser_try_delim (parser, '*'))
{
value = gtk_css_calc_value_parse_product (parser, actual_flags);
if (value == NULL)
@@ -379,7 +391,7 @@ gtk_css_calc_value_parse_product (GtkCssParser *parser,
_gtk_css_value_unref (result);
result = temp;
}
else if (_gtk_css_parser_try (parser, "/", TRUE))
else if (gtk_css_parser_try_delim (parser, '/'))
{
value = gtk_css_calc_value_parse_product (parser, GTK_CSS_PARSE_NUMBER);
if (value == NULL)
@@ -391,14 +403,17 @@ gtk_css_calc_value_parse_product (GtkCssParser *parser,
}
else
{
g_assert_not_reached ();
goto fail;
break;
}
}
if (is_number (result) && !(flags & GTK_CSS_PARSE_NUMBER))
{
_gtk_css_parser_error (parser, "calc() product term has no units");
gtk_css_parser_error (parser,
GTK_CSS_PARSER_ERROR_SYNTAX,
&start,
gtk_css_parser_get_start_location (parser),
"calc() product term has no units");
goto fail;
}
@@ -419,17 +434,17 @@ gtk_css_calc_value_parse_sum (GtkCssParser *parser,
if (result == NULL)
return NULL;
while (_gtk_css_parser_begins_with (parser, '+') || _gtk_css_parser_begins_with (parser, '-'))
while (TRUE)
{
GtkCssValue *next, *temp;
if (_gtk_css_parser_try (parser, "+", TRUE))
if (gtk_css_parser_try_delim (parser, '+'))
{
next = gtk_css_calc_value_parse_product (parser, flags);
if (next == NULL)
goto fail;
}
else if (_gtk_css_parser_try (parser, "-", TRUE))
else if (gtk_css_parser_try_delim (parser, '-'))
{
temp = gtk_css_calc_value_parse_product (parser, flags);
if (temp == NULL)
@@ -439,8 +454,7 @@ gtk_css_calc_value_parse_sum (GtkCssParser *parser,
}
else
{
g_assert_not_reached ();
goto fail;
break;
}
temp = gtk_css_number_value_add (result, next);
@@ -456,32 +470,45 @@ fail:
return NULL;
}
typedef struct
{
GtkCssNumberParseFlags flags;
GtkCssValue *value;
} ParseCalcData;
static guint
gtk_css_calc_value_parse_arg (GtkCssParser *parser,
guint arg,
gpointer data_)
{
ParseCalcData *data = data_;
data->value = gtk_css_calc_value_parse_sum (parser, data->flags);
if (data->value == NULL)
return 0;
return 1;
}
GtkCssValue *
gtk_css_calc_value_parse (GtkCssParser *parser,
GtkCssNumberParseFlags flags)
{
GtkCssValue *value;
ParseCalcData data;
/* This can only be handled at compute time, we allow '-' after all */
flags &= ~GTK_CSS_POSITIVE_ONLY;
data.flags = flags & ~GTK_CSS_POSITIVE_ONLY;
data.value = NULL;
if (!_gtk_css_parser_try (parser, "calc(", TRUE))
if (!gtk_css_parser_has_function (parser, "calc"))
{
_gtk_css_parser_error (parser, "Expected 'calc('");
gtk_css_parser_error_syntax (parser, "Expected 'calc('");
return NULL;
}
value = gtk_css_calc_value_parse_sum (parser, flags);
if (value == NULL)
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_calc_value_parse_arg, &data))
return NULL;
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_value_unref (value);
_gtk_css_parser_error (parser, "Expected ')' after calc() statement");
return NULL;
}
return value;
return data.value;
}
+129 -200
View File
@@ -22,9 +22,10 @@
#include "gtkcssrgbavalueprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkhslaprivate.h"
#include "gtkprivate.h"
#include "gtkstylepropertyprivate.h"
#include "gtkprivate.h"
#include "gdk/gdkrgbaprivate.h"
typedef enum {
COLOR_TYPE_LITERAL,
@@ -510,233 +511,161 @@ _gtk_css_color_value_new_current_color (void)
return _gtk_css_value_ref (&current_color);
}
typedef enum {
COLOR_RGBA,
COLOR_RGB,
COLOR_LIGHTER,
COLOR_DARKER,
COLOR_SHADE,
COLOR_ALPHA,
COLOR_MIX
} ColorParseType;
static GtkCssValue *
_gtk_css_color_value_parse_function (GtkCssParser *parser,
ColorParseType color)
typedef struct
{
GtkCssValue *value;
GtkCssValue *child1, *child2;
double d;
GtkCssValue *color;
GtkCssValue *color2;
double value;
} ColorFunctionData;
if (!_gtk_css_parser_try (parser, "(", TRUE))
{
_gtk_css_parser_error (parser, "Missing opening bracket in color definition");
return NULL;
}
static guint
parse_color_mix (GtkCssParser *parser,
guint arg,
gpointer data_)
{
ColorFunctionData *data = data_;
if (color == COLOR_RGB || color == COLOR_RGBA)
{
GdkRGBA rgba;
double tmp;
guint i;
switch (arg)
{
case 0:
data->color = _gtk_css_color_value_parse (parser);
if (data->color == NULL)
return 0;
return 1;
for (i = 0; i < 3; i++)
{
if (i > 0 && !_gtk_css_parser_try (parser, ",", TRUE))
{
_gtk_css_parser_error (parser, "Expected ',' in color definition");
return NULL;
}
case 1:
data->color2 = _gtk_css_color_value_parse (parser);
if (data->color2 == NULL)
return 0;
return 1;
if (!_gtk_css_parser_try_double (parser, &tmp))
{
_gtk_css_parser_error (parser, "Invalid number for color value");
return NULL;
}
if (_gtk_css_parser_try (parser, "%", TRUE))
tmp /= 100.0;
else
tmp /= 255.0;
if (i == 0)
rgba.red = tmp;
else if (i == 1)
rgba.green = tmp;
else if (i == 2)
rgba.blue = tmp;
else
g_assert_not_reached ();
}
case 2:
if (!gtk_css_parser_consume_number (parser, &data->value))
return 0;
return 1;
if (color == COLOR_RGBA)
{
if (i > 0 && !_gtk_css_parser_try (parser, ",", TRUE))
{
_gtk_css_parser_error (parser, "Expected ',' in color definition");
return NULL;
}
default:
g_return_val_if_reached (0);
}
}
if (!_gtk_css_parser_try_double (parser, &rgba.alpha))
{
_gtk_css_parser_error (parser, "Invalid number for alpha value");
return NULL;
}
}
else
rgba.alpha = 1.0;
value = _gtk_css_color_value_new_literal (&rgba);
}
else
{
child1 = _gtk_css_color_value_parse (parser);
if (child1 == NULL)
return NULL;
static guint
parse_color_number (GtkCssParser *parser,
guint arg,
gpointer data_)
{
ColorFunctionData *data = data_;
if (color == COLOR_MIX)
{
if (!_gtk_css_parser_try (parser, ",", TRUE))
{
_gtk_css_parser_error (parser, "Expected ',' in color definition");
_gtk_css_value_unref (child1);
return NULL;
}
switch (arg)
{
case 0:
data->color = _gtk_css_color_value_parse (parser);
if (data->color == NULL)
return 0;
return 1;
child2 = _gtk_css_color_value_parse (parser);
if (child2 == NULL)
{
_gtk_css_value_unref (child1);
return NULL;
}
}
else
child2 = NULL;
case 1:
if (!gtk_css_parser_consume_number (parser, &data->value))
return 0;
return 1;
if (color == COLOR_LIGHTER)
d = 1.3;
else if (color == COLOR_DARKER)
d = 0.7;
else
{
if (!_gtk_css_parser_try (parser, ",", TRUE))
{
_gtk_css_parser_error (parser, "Expected ',' in color definition");
_gtk_css_value_unref (child1);
if (child2)
_gtk_css_value_unref (child2);
return NULL;
}
default:
g_return_val_if_reached (0);
}
}
if (!_gtk_css_parser_try_double (parser, &d))
{
_gtk_css_parser_error (parser, "Expected number in color definition");
_gtk_css_value_unref (child1);
if (child2)
_gtk_css_value_unref (child2);
return NULL;
}
}
switch (color)
{
case COLOR_LIGHTER:
case COLOR_DARKER:
case COLOR_SHADE:
value = _gtk_css_color_value_new_shade (child1, d);
break;
case COLOR_ALPHA:
value = _gtk_css_color_value_new_alpha (child1, d);
break;
case COLOR_MIX:
value = _gtk_css_color_value_new_mix (child1, child2, d);
break;
case COLOR_RGB:
case COLOR_RGBA:
default:
g_assert_not_reached ();
value = NULL;
}
_gtk_css_value_unref (child1);
if (child2)
_gtk_css_value_unref (child2);
}
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_parser_error (parser, "Expected ')' in color definition");
_gtk_css_value_unref (value);
return NULL;
}
return value;
gboolean
gtk_css_color_value_can_parse (GtkCssParser *parser)
{
/* This is way too generous, but meh... */
return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_IDENT)
|| gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_AT_KEYWORD)
|| gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_HASH_ID)
|| gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_HASH_UNRESTRICTED)
|| gtk_css_parser_has_function (parser, "lighter")
|| gtk_css_parser_has_function (parser, "darker")
|| gtk_css_parser_has_function (parser, "shade")
|| gtk_css_parser_has_function (parser, "alpha")
|| gtk_css_parser_has_function (parser, "mix")
|| gtk_css_parser_has_function (parser, "rgb")
|| gtk_css_parser_has_function (parser, "rgba");
}
GtkCssValue *
_gtk_css_color_value_parse (GtkCssParser *parser)
{
ColorFunctionData data = { NULL, };
GtkCssValue *value;
GdkRGBA rgba;
guint color;
const char *names[] = {"rgba", "rgb", "lighter", "darker", "shade", "alpha", "mix"};
char *name;
if (_gtk_css_parser_try (parser, "currentColor", TRUE))
return _gtk_css_color_value_new_current_color ();
if (_gtk_css_parser_try (parser, "transparent", TRUE))
if (gtk_css_parser_try_ident (parser, "currentColor"))
{
GdkRGBA transparent = { 0, 0, 0, 0 };
return _gtk_css_color_value_new_literal (&transparent);
return _gtk_css_color_value_new_current_color ();
}
if (_gtk_css_parser_try (parser, "@", FALSE))
else if (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_AT_KEYWORD))
{
name = _gtk_css_parser_try_name (parser, TRUE);
const GtkCssToken *token = gtk_css_parser_get_token (parser);
if (name)
{
value = _gtk_css_color_value_new_name (name);
}
value = _gtk_css_color_value_new_name (token->string.string);
gtk_css_parser_consume_token (parser);
return value;
}
else if (gtk_css_parser_has_function (parser, "lighter"))
{
if (gtk_css_parser_consume_function (parser, 1, 1, parse_color_number, &data))
value = _gtk_css_color_value_new_shade (data.color, 1.3);
else
{
_gtk_css_parser_error (parser, "'%s' is not a valid color color name", name);
value = NULL;
}
value = NULL;
g_free (name);
g_clear_pointer (&data.color, gtk_css_value_unref);
return value;
}
else if (gtk_css_parser_has_function (parser, "darker"))
{
if (gtk_css_parser_consume_function (parser, 1, 1, parse_color_number, &data))
value = _gtk_css_color_value_new_shade (data.color, 0.7);
else
value = NULL;
g_clear_pointer (&data.color, gtk_css_value_unref);
return value;
}
else if (gtk_css_parser_has_function (parser, "shade"))
{
if (gtk_css_parser_consume_function (parser, 2, 2, parse_color_number, &data))
value = _gtk_css_color_value_new_shade (data.color, data.value);
else
value = NULL;
g_clear_pointer (&data.color, gtk_css_value_unref);
return value;
}
else if (gtk_css_parser_has_function (parser, "alpha"))
{
if (gtk_css_parser_consume_function (parser, 2, 2, parse_color_number, &data))
value = _gtk_css_color_value_new_alpha (data.color, data.value);
else
value = NULL;
g_clear_pointer (&data.color, gtk_css_value_unref);
return value;
}
else if (gtk_css_parser_has_function (parser, "mix"))
{
if (gtk_css_parser_consume_function (parser, 3, 3, parse_color_mix, &data))
value = _gtk_css_color_value_new_mix (data.color, data.color2, data.value);
else
value = NULL;
g_clear_pointer (&data.color, gtk_css_value_unref);
g_clear_pointer (&data.color2, gtk_css_value_unref);
return value;
}
for (color = 0; color < G_N_ELEMENTS (names); color++)
{
if (_gtk_css_parser_try (parser, names[color], TRUE))
break;
}
if (color < G_N_ELEMENTS (names))
return _gtk_css_color_value_parse_function (parser, color);
if (_gtk_css_parser_try_hash_color (parser, &rgba))
if (gdk_rgba_parser_parse (parser, &rgba))
return _gtk_css_color_value_new_literal (&rgba);
name = _gtk_css_parser_try_name (parser, TRUE);
if (name)
{
if (gdk_rgba_parse (&rgba, name))
{
value = _gtk_css_color_value_new_literal (&rgba);
}
else
{
_gtk_css_parser_error (parser, "'%s' is not a valid color name", name);
value = NULL;
}
g_free (name);
return value;
}
_gtk_css_parser_error (parser, "Not a color definition");
return NULL;
else
return NULL;
}
+1
View File
@@ -39,6 +39,7 @@ GtkCssValue * _gtk_css_color_value_new_mix (GtkCssValue *color1,
gdouble factor);
GtkCssValue * _gtk_css_color_value_new_current_color (void);
gboolean gtk_css_color_value_can_parse (GtkCssParser *parser);
GtkCssValue * _gtk_css_color_value_parse (GtkCssParser *parser);
GtkCssValue * _gtk_css_color_value_resolve (GtkCssValue *color,
+113
View File
@@ -325,3 +325,116 @@ gtk_css_dimension_value_new (double value,
return result;
}
GtkCssValue *
gtk_css_dimension_value_parse (GtkCssParser *parser,
GtkCssNumberParseFlags flags)
{
static const struct {
const char *name;
GtkCssUnit unit;
GtkCssNumberParseFlags required_flags;
} units[] = {
{ "px", GTK_CSS_PX, GTK_CSS_PARSE_LENGTH },
{ "pt", GTK_CSS_PT, GTK_CSS_PARSE_LENGTH },
{ "em", GTK_CSS_EM, GTK_CSS_PARSE_LENGTH },
{ "ex", GTK_CSS_EX, GTK_CSS_PARSE_LENGTH },
{ "rem", GTK_CSS_REM, GTK_CSS_PARSE_LENGTH },
{ "pc", GTK_CSS_PC, GTK_CSS_PARSE_LENGTH },
{ "in", GTK_CSS_IN, GTK_CSS_PARSE_LENGTH },
{ "cm", GTK_CSS_CM, GTK_CSS_PARSE_LENGTH },
{ "mm", GTK_CSS_MM, GTK_CSS_PARSE_LENGTH },
{ "rad", GTK_CSS_RAD, GTK_CSS_PARSE_ANGLE },
{ "deg", GTK_CSS_DEG, GTK_CSS_PARSE_ANGLE },
{ "grad", GTK_CSS_GRAD, GTK_CSS_PARSE_ANGLE },
{ "turn", GTK_CSS_TURN, GTK_CSS_PARSE_ANGLE },
{ "s", GTK_CSS_S, GTK_CSS_PARSE_TIME },
{ "ms", GTK_CSS_MS, GTK_CSS_PARSE_TIME }
};
const GtkCssToken *token;
GtkCssValue *result;
GtkCssUnit unit;
double number;
token = gtk_css_parser_get_token (parser);
/* Handle percentages first */
if (gtk_css_token_is (token, GTK_CSS_TOKEN_PERCENTAGE))
{
if (!(flags & GTK_CSS_PARSE_PERCENT))
{
gtk_css_parser_error_value (parser, "Percentages are not allowed here");
return NULL;
}
number = token->number.number;
unit = GTK_CSS_PERCENT;
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_NUMBER) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_NUMBER))
{
number = token->number.number;
if (number == 0.0)
{
if (flags & GTK_CSS_PARSE_NUMBER)
unit = GTK_CSS_NUMBER;
else if (flags & GTK_CSS_PARSE_LENGTH)
unit = GTK_CSS_PX;
else if (flags & GTK_CSS_PARSE_ANGLE)
unit = GTK_CSS_DEG;
else if (flags & GTK_CSS_PARSE_TIME)
unit = GTK_CSS_S;
else
unit = GTK_CSS_PERCENT;
}
else if (flags & GTK_CSS_PARSE_NUMBER)
{
unit = GTK_CSS_NUMBER;
}
else
{
gtk_css_parser_error_syntax (parser, "Unit is missing.");
return NULL;
}
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_DIMENSION))
{
guint i;
for (i = 0; i < G_N_ELEMENTS (units); i++)
{
if (flags & units[i].required_flags &&
g_ascii_strcasecmp (token->dimension.dimension, units[i].name) == 0)
break;
}
if (i >= G_N_ELEMENTS (units))
{
gtk_css_parser_error_syntax (parser, "'%s' is not a valid unit.", token->dimension.dimension);
return NULL;
}
unit = units[i].unit;
number = token->dimension.value;
}
else
{
gtk_css_parser_error_syntax (parser, "Expected a number");
return NULL;
}
if (flags & GTK_CSS_POSITIVE_ONLY &&
number < 0)
{
gtk_css_parser_error_value (parser, "negative values are not allowed.");
return NULL;
}
result = gtk_css_dimension_value_new (number, unit);
gtk_css_parser_consume_token (parser);
return result;
}
+100 -83
View File
@@ -188,7 +188,7 @@ _gtk_css_ease_value_new_steps (guint n_steps,
static const struct {
const char *name;
guint is_bezier :1;
guint needs_custom :1;
guint is_function :1;
double values[4];
} parser_values[] = {
{ "linear", TRUE, FALSE, { 0.0, 0.0, 1.0, 1.0 } },
@@ -209,93 +209,107 @@ _gtk_css_ease_value_can_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (parser_values); i++)
{
if (_gtk_css_parser_has_prefix (parser, parser_values[i].name))
return TRUE;
if (parser_values[i].is_function)
{
if (gtk_css_parser_has_function (parser, parser_values[i].name))
return TRUE;
}
else
{
if (gtk_css_parser_has_ident (parser, parser_values[i].name))
return TRUE;
}
}
return FALSE;
}
static guint
gtk_css_ease_value_parse_cubic_bezier_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
double *values = data;
if (!gtk_css_parser_consume_number (parser, &values[arg]))
return 0;
if (arg % 2 == 0)
{
if (values[arg] < 0 || values[arg] > 1.0)
{
gtk_css_parser_error_value (parser, "value %g out of range. Must be from 0.0 to 1.0", values[arg]);
return 0;
}
}
return 1;
}
static GtkCssValue *
gtk_css_ease_value_parse_cubic_bezier (GtkCssParser *parser)
{
double values[4];
guint i;
for (i = 0; i < 4; i++)
{
if (!_gtk_css_parser_try (parser, i ? "," : "(", TRUE))
{
_gtk_css_parser_error (parser, "Expected '%s'", i ? "," : "(");
return NULL;
}
if (!_gtk_css_parser_try_double (parser, &values[i]))
{
_gtk_css_parser_error (parser, "Expected a number");
return NULL;
}
if ((i == 0 || i == 2) &&
(values[i] < 0 || values[i] > 1.0))
{
_gtk_css_parser_error (parser, "value %g out of range. Must be from 0.0 to 1.0", values[i]);
return NULL;
}
}
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_parser_error (parser, "Missing closing ')' for cubic-bezier");
return NULL;
}
if (!gtk_css_parser_consume_function (parser, 4, 4, gtk_css_ease_value_parse_cubic_bezier_arg, values))
return NULL;
return _gtk_css_ease_value_new_cubic_bezier (values[0], values[1], values[2], values[3]);
}
typedef struct
{
int n_steps;
gboolean start;
} ParseStepsData;
static guint
gtk_css_ease_value_parse_steps_arg (GtkCssParser *parser,
guint arg,
gpointer data_)
{
ParseStepsData *data = data_;
switch (arg)
{
case 0:
if (!gtk_css_parser_consume_integer (parser, &data->n_steps))
{
return 0;
}
else if (data->n_steps < 1)
{
gtk_css_parser_error_value (parser, "Number of steps must be > 0");
return 0;
}
return 1;
case 1:
if (gtk_css_parser_try_ident (parser, "start"))
data->start = TRUE;
else if (gtk_css_parser_try_ident (parser, "end"))
data->start = FALSE;
else
{
gtk_css_parser_error_syntax (parser, "Only allowed values are 'start' and 'end'");
return 0;
}
return 1;
default:
g_return_val_if_reached (0);
}
}
static GtkCssValue *
gtk_css_ease_value_parse_steps (GtkCssParser *parser)
{
int n_steps;
gboolean start;
ParseStepsData data = { 0, FALSE };
if (!_gtk_css_parser_try (parser, "(", TRUE))
{
_gtk_css_parser_error (parser, "Expected '('");
return NULL;
}
if (!gtk_css_parser_consume_function (parser, 1, 2, gtk_css_ease_value_parse_steps_arg, &data))
return NULL;
if (!_gtk_css_parser_try_int (parser, &n_steps))
{
_gtk_css_parser_error (parser, "Expected number of steps");
return NULL;
}
else if (n_steps < 1)
{
_gtk_css_parser_error (parser, "Number of steps must be > 0");
return NULL;
}
if (_gtk_css_parser_try (parser, ",", TRUE))
{
if (_gtk_css_parser_try (parser, "start", TRUE))
start = TRUE;
else if (_gtk_css_parser_try (parser, "end", TRUE))
start = FALSE;
else
{
_gtk_css_parser_error (parser, "Only allowed values are 'start' and 'end'");
return NULL;
}
}
else
start = FALSE;
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_parser_error (parser, "Missing closing ')' for steps");
return NULL;
}
return _gtk_css_ease_value_new_steps (n_steps, start);
return _gtk_css_ease_value_new_steps (data.n_steps, data.start);
}
GtkCssValue *
@@ -307,30 +321,33 @@ _gtk_css_ease_value_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (parser_values); i++)
{
if (_gtk_css_parser_try (parser, parser_values[i].name, FALSE))
if (parser_values[i].is_function)
{
if (parser_values[i].needs_custom)
if (gtk_css_parser_has_function (parser, parser_values[i].name))
{
if (parser_values[i].is_bezier)
return gtk_css_ease_value_parse_cubic_bezier (parser);
else
return gtk_css_ease_value_parse_steps (parser);
}
_gtk_css_parser_skip_whitespace (parser);
if (parser_values[i].is_bezier)
return _gtk_css_ease_value_new_cubic_bezier (parser_values[i].values[0],
parser_values[i].values[1],
parser_values[i].values[2],
parser_values[i].values[3]);
else
return _gtk_css_ease_value_new_steps (parser_values[i].values[0],
parser_values[i].values[1] != 0.0);
}
else
{
if (gtk_css_parser_try_ident (parser, parser_values[i].name))
{
if (parser_values[i].is_bezier)
return _gtk_css_ease_value_new_cubic_bezier (parser_values[i].values[0],
parser_values[i].values[1],
parser_values[i].values[2],
parser_values[i].values[3]);
else
return _gtk_css_ease_value_new_steps (parser_values[i].values[0],
parser_values[i].values[1] != 0.0);
}
}
}
_gtk_css_parser_error (parser, "Unknown value");
gtk_css_parser_error_syntax (parser, "Expected a valid ease value");
return NULL;
}
+40 -82
View File
@@ -117,7 +117,7 @@ _gtk_css_border_style_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (border_style_values); i++)
{
if (_gtk_css_parser_try (parser, border_style_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, border_style_values[i].name))
return _gtk_css_value_ref (&border_style_values[i]);
}
@@ -180,7 +180,7 @@ _gtk_css_blend_mode_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (blend_mode_values); i++)
{
if (_gtk_css_parser_try (parser, blend_mode_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, blend_mode_values[i].name))
return _gtk_css_value_ref (&blend_mode_values[i]);
}
@@ -323,7 +323,7 @@ _gtk_css_font_size_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (font_size_values); i++)
{
if (_gtk_css_parser_try (parser, font_size_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, font_size_values[i].name))
return _gtk_css_value_ref (&font_size_values[i]);
}
@@ -373,7 +373,7 @@ _gtk_css_font_style_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (font_style_values); i++)
{
if (_gtk_css_parser_try (parser, font_style_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, font_style_values[i].name))
return _gtk_css_value_ref (&font_style_values[i]);
}
@@ -407,27 +407,27 @@ gtk_css_value_font_weight_compute (GtkCssValue *value,
return _gtk_css_value_ref (value);
if (parent_style)
parent_value = gtk_css_style_get_value (parent_style, property_id)->value;
parent_value = _gtk_css_number_value_get (gtk_css_style_get_value (parent_style, property_id), 100);
else
parent_value = 400;
if (value->value == BOLDER)
{
if (parent_value < 400)
new_weight = PANGO_WEIGHT_NORMAL;
else if (parent_value < 600)
new_weight = PANGO_WEIGHT_BOLD;
if (parent_value < 350)
new_weight = 400;
else if (parent_value < 550)
new_weight = 700;
else
new_weight = PANGO_WEIGHT_HEAVY;
new_weight = 900;
}
else if (value->value == LIGHTER)
{
if (parent_value > 700)
new_weight = PANGO_WEIGHT_BOLD;
else if (parent_value > 500)
new_weight = PANGO_WEIGHT_NORMAL;
if (parent_value > 750)
new_weight = 700;
else if (parent_value > 550)
new_weight = 400;
else
new_weight = PANGO_WEIGHT_THIN;
new_weight = 100;
}
else
{
@@ -435,30 +435,14 @@ gtk_css_value_font_weight_compute (GtkCssValue *value,
new_weight = PANGO_WEIGHT_NORMAL;
}
return _gtk_css_font_weight_value_new (new_weight);
}
static GtkCssValue *
gtk_css_value_font_weight_transition (GtkCssValue *start,
GtkCssValue *end,
guint property_id,
double progress)
{
PangoWeight new_weight;
if (start->value < 0 || end->value < 0)
return NULL;
new_weight = (start->value + end->value + 50) / 200 * 100;
return _gtk_css_font_weight_value_new (new_weight);
return _gtk_css_number_value_new (new_weight, GTK_CSS_NUMBER);
}
static const GtkCssValueClass GTK_CSS_VALUE_FONT_WEIGHT = {
gtk_css_value_enum_free,
gtk_css_value_font_weight_compute,
gtk_css_value_enum_equal,
gtk_css_value_font_weight_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
@@ -467,36 +451,10 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_WEIGHT = {
static GtkCssValue font_weight_values[] = {
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, BOLDER, "bolder" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, LIGHTER, "lighter" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_THIN, "100" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_ULTRALIGHT, "200" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_LIGHT, "300" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_NORMAL, "normal" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_MEDIUM, "500" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_SEMIBOLD, "600" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_BOLD, "bold" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_ULTRABOLD, "800" },
{ &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_HEAVY, "900" }
};
GtkCssValue *
_gtk_css_font_weight_value_new (PangoWeight font_weight)
{
guint i;
gint w;
w = ((font_weight + 50) / 100) * 100;
for (i = 2; i < G_N_ELEMENTS (font_weight_values); i++)
{
if (font_weight_values[i].value == w)
return _gtk_css_value_ref (&font_weight_values[i]);
}
g_return_val_if_reached (NULL);
}
GtkCssValue *
_gtk_css_font_weight_value_try_parse (GtkCssParser *parser)
gtk_css_font_weight_value_try_parse (GtkCssParser *parser)
{
guint i;
@@ -504,20 +462,20 @@ _gtk_css_font_weight_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (font_weight_values); i++)
{
if (_gtk_css_parser_try (parser, font_weight_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, font_weight_values[i].name))
return _gtk_css_value_ref (&font_weight_values[i]);
}
/* special cases go here */
if (_gtk_css_parser_try (parser, "400", TRUE))
return _gtk_css_value_ref (&font_weight_values[5]);
if (_gtk_css_parser_try (parser, "700", TRUE))
return _gtk_css_value_ref (&font_weight_values[8]);
if (gtk_css_parser_try_ident (parser, "normal"))
return _gtk_css_number_value_new (PANGO_WEIGHT_NORMAL, GTK_CSS_NUMBER);
if (gtk_css_parser_try_ident (parser, "bold"))
return _gtk_css_number_value_new (PANGO_WEIGHT_BOLD, GTK_CSS_NUMBER);
return NULL;
}
PangoWeight
_gtk_css_font_weight_value_get (const GtkCssValue *value)
gtk_css_font_weight_value_get (const GtkCssValue *value)
{
g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_WEIGHT, PANGO_WEIGHT_NORMAL);
@@ -568,7 +526,7 @@ _gtk_css_font_stretch_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (font_stretch_values); i++)
{
if (_gtk_css_parser_try (parser, font_stretch_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, font_stretch_values[i].name))
return _gtk_css_value_ref (&font_stretch_values[i]);
}
@@ -618,7 +576,7 @@ _gtk_css_text_decoration_line_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (text_decoration_line_values); i++)
{
if (_gtk_css_parser_try (parser, text_decoration_line_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, text_decoration_line_values[i].name))
return _gtk_css_value_ref (&text_decoration_line_values[i]);
}
@@ -668,7 +626,7 @@ _gtk_css_text_decoration_style_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (text_decoration_style_values); i++)
{
if (_gtk_css_parser_try (parser, text_decoration_style_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, text_decoration_style_values[i].name))
return _gtk_css_value_ref (&text_decoration_style_values[i]);
}
@@ -724,7 +682,7 @@ _gtk_css_area_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (area_values); i++)
{
if (_gtk_css_parser_try (parser, area_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, area_values[i].name))
return _gtk_css_value_ref (&area_values[i]);
}
@@ -784,7 +742,7 @@ _gtk_css_direction_value_try_parse (GtkCssParser *parser)
*/
for (i = G_N_ELEMENTS (direction_values) - 1; i >= 0; i--)
{
if (_gtk_css_parser_try (parser, direction_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, direction_values[i].name))
return _gtk_css_value_ref (&direction_values[i]);
}
@@ -839,7 +797,7 @@ _gtk_css_play_state_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (play_state_values); i++)
{
if (_gtk_css_parser_try (parser, play_state_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, play_state_values[i].name))
return _gtk_css_value_ref (&play_state_values[i]);
}
@@ -896,7 +854,7 @@ _gtk_css_fill_mode_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (fill_mode_values); i++)
{
if (_gtk_css_parser_try (parser, fill_mode_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, fill_mode_values[i].name))
return _gtk_css_value_ref (&fill_mode_values[i]);
}
@@ -952,7 +910,7 @@ _gtk_css_icon_style_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (icon_style_values); i++)
{
if (_gtk_css_parser_try (parser, icon_style_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, icon_style_values[i].name))
return _gtk_css_value_ref (&icon_style_values[i]);
}
@@ -1008,7 +966,7 @@ _gtk_css_font_kerning_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (font_kerning_values); i++)
{
if (_gtk_css_parser_try (parser, font_kerning_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, font_kerning_values[i].name))
return _gtk_css_value_ref (&font_kerning_values[i]);
}
@@ -1064,7 +1022,7 @@ _gtk_css_font_variant_position_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (font_variant_position_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_position_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, font_variant_position_values[i].name))
return _gtk_css_value_ref (&font_variant_position_values[i]);
}
@@ -1124,7 +1082,7 @@ _gtk_css_font_variant_caps_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (font_variant_caps_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_caps_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, font_variant_caps_values[i].name))
return _gtk_css_value_ref (&font_variant_caps_values[i]);
}
@@ -1179,7 +1137,7 @@ _gtk_css_font_variant_alternate_value_try_parse (GtkCssParser *parser)
for (i = 0; i < G_N_ELEMENTS (font_variant_alternate_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_alternate_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, font_variant_alternate_values[i].name))
return _gtk_css_value_ref (&font_variant_alternate_values[i]);
}
@@ -1310,7 +1268,7 @@ _gtk_css_font_variant_ligature_try_parse_one (GtkCssParser *parser,
for (i = 0; i < G_N_ELEMENTS (font_variant_ligature_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_ligature_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, font_variant_ligature_values[i].name))
{
value = font_variant_ligature_values[i].value;
break;
@@ -1412,7 +1370,7 @@ _gtk_css_font_variant_numeric_try_parse_one (GtkCssParser *parser,
for (i = 0; i < G_N_ELEMENTS (font_variant_numeric_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_numeric_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, font_variant_numeric_values[i].name))
{
value = font_variant_numeric_values[i].value;
break;
@@ -1554,7 +1512,7 @@ _gtk_css_font_variant_east_asian_try_parse_one (GtkCssParser *pars
for (i = 0; i < G_N_ELEMENTS (font_variant_east_asian_values); i++)
{
if (_gtk_css_parser_try (parser, font_variant_east_asian_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, font_variant_east_asian_values[i].name))
{
value = font_variant_east_asian_values[i].value;
break;
+2 -3
View File
@@ -45,9 +45,8 @@ GtkCssValue * _gtk_css_font_style_value_new (PangoStyle style)
GtkCssValue * _gtk_css_font_style_value_try_parse (GtkCssParser *parser);
PangoStyle _gtk_css_font_style_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_font_weight_value_new (PangoWeight weight);
GtkCssValue * _gtk_css_font_weight_value_try_parse (GtkCssParser *parser);
PangoWeight _gtk_css_font_weight_value_get (const GtkCssValue *value);
GtkCssValue * gtk_css_font_weight_value_try_parse (GtkCssParser *parser);
PangoWeight gtk_css_font_weight_value_get (const GtkCssValue *value);
GtkCssValue * _gtk_css_font_stretch_value_new (PangoStretch stretch);
GtkCssValue * _gtk_css_font_stretch_value_try_parse (GtkCssParser *parser);
+119 -95
View File
@@ -729,96 +729,46 @@ gtk_css_filter_value_is_none (const GtkCssValue *value)
return value->n_filters == 0;
}
static gboolean
gtk_css_filter_parse (GtkCssFilter *filter,
GtkCssParser *parser)
static guint
gtk_css_filter_parse_number (GtkCssParser *parser,
guint n,
gpointer data)
{
if (_gtk_css_parser_try (parser, "brightness(", TRUE))
{
filter->type = GTK_CSS_FILTER_BRIGHTNESS;
GtkCssValue **values = data;
filter->brightness.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
if (filter->brightness.value == NULL)
return FALSE;
}
else if (_gtk_css_parser_try (parser, "contrast(", TRUE))
{
filter->type = GTK_CSS_FILTER_CONTRAST;
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
if (values[n] == NULL)
return 0;
filter->contrast.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
if (filter->contrast.value == NULL)
return FALSE;
}
else if (_gtk_css_parser_try (parser, "grayscale(", TRUE))
{
filter->type = GTK_CSS_FILTER_GRAYSCALE;
return 1;
}
filter->grayscale.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
if (filter->grayscale.value == NULL)
return FALSE;
}
else if (_gtk_css_parser_try (parser, "hue-rotate(", TRUE))
{
filter->type = GTK_CSS_FILTER_HUE_ROTATE;
static guint
gtk_css_filter_parse_length (GtkCssParser *parser,
guint n,
gpointer data)
{
GtkCssValue **values = data;
filter->hue_rotate.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (filter->hue_rotate.value == NULL)
return FALSE;
}
else if (_gtk_css_parser_try (parser, "invert(", TRUE))
{
filter->type = GTK_CSS_FILTER_INVERT;
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (values[n] == NULL)
return 0;
filter->invert.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
if (filter->invert.value == NULL)
return FALSE;
}
else if (_gtk_css_parser_try (parser, "opacity(", TRUE))
{
filter->type = GTK_CSS_FILTER_OPACITY;
return 1;
}
filter->opacity.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
if (filter->opacity.value == NULL)
return FALSE;
}
else if (_gtk_css_parser_try (parser, "saturate(", TRUE))
{
filter->type = GTK_CSS_FILTER_SATURATE;
static guint
gtk_css_filter_parse_angle (GtkCssParser *parser,
guint n,
gpointer data)
{
GtkCssValue **values = data;
filter->saturate.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
if (filter->saturate.value == NULL)
return FALSE;
}
else if (_gtk_css_parser_try (parser, "sepia(", TRUE))
{
filter->type = GTK_CSS_FILTER_SEPIA;
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (values[n] == NULL)
return 0;
filter->sepia.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_PARSE_PERCENT);
if (filter->sepia.value == NULL)
return FALSE;
}
else if (_gtk_css_parser_try (parser, "blur(", TRUE))
{
filter->type = GTK_CSS_FILTER_BLUR;
filter->blur.value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (filter->blur.value == NULL)
return FALSE;
}
else
{
_gtk_css_parser_error (parser, "unknown syntax for filter");
return FALSE;
}
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
gtk_css_filter_clear (filter);
_gtk_css_parser_error (parser, "Expected closing ')'");
return FALSE;
}
return TRUE;
return 1;
}
GtkCssValue *
@@ -828,25 +778,91 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
GArray *array;
guint i;
if (_gtk_css_parser_try (parser, "none", TRUE))
if (gtk_css_parser_try_ident (parser, "none"))
return gtk_css_filter_value_new_none ();
array = g_array_new (FALSE, FALSE, sizeof (GtkCssFilter));
do {
GtkCssFilter filter;
while (TRUE)
{
GtkCssFilter filter;
if (!gtk_css_filter_parse (&filter, parser))
{
for (i = 0; i < array->len; i++)
{
gtk_css_filter_clear (&g_array_index (array, GtkCssFilter, i));
}
g_array_free (array, TRUE);
return NULL;
}
g_array_append_val (array, filter);
} while (!_gtk_css_parser_begins_with (parser, ';'));
if (gtk_css_parser_has_function (parser, "blur"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_length, &filter.blur.value))
goto fail;
filter.type = GTK_CSS_FILTER_BLUR;
}
else if (gtk_css_parser_has_function (parser, "brightness"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_number, &filter.brightness.value))
goto fail;
filter.type = GTK_CSS_FILTER_BRIGHTNESS;
}
else if (gtk_css_parser_has_function (parser, "contrast"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_number, &filter.contrast.value))
goto fail;
filter.type = GTK_CSS_FILTER_CONTRAST;
}
else if (gtk_css_parser_has_function (parser, "grayscale"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_number, &filter.grayscale.value))
goto fail;
filter.type = GTK_CSS_FILTER_GRAYSCALE;
}
else if (gtk_css_parser_has_function (parser, "hue-rotate"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_angle, &filter.blur.value))
goto fail;
filter.type = GTK_CSS_FILTER_HUE_ROTATE;
}
else if (gtk_css_parser_has_function (parser, "invert"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_number, &filter.invert.value))
goto fail;
filter.type = GTK_CSS_FILTER_INVERT;
}
else if (gtk_css_parser_has_function (parser, "opacity"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_number, &filter.opacity.value))
goto fail;
filter.type = GTK_CSS_FILTER_OPACITY;
}
else if (gtk_css_parser_has_function (parser, "saturate"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_number, &filter.saturate.value))
goto fail;
filter.type = GTK_CSS_FILTER_SATURATE;
}
else if (gtk_css_parser_has_function (parser, "sepia"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_filter_parse_number, &filter.sepia.value))
goto fail;
filter.type = GTK_CSS_FILTER_SEPIA;
}
else
{
break;
}
g_array_append_val (array, filter);
}
if (array->len == 0)
{
gtk_css_parser_error_syntax (parser, "Expected a filter");
goto fail;
}
value = gtk_css_filter_value_alloc (array->len);
memcpy (value->filters, array->data, sizeof (GtkCssFilter) * array->len);
@@ -854,6 +870,14 @@ gtk_css_filter_value_parse (GtkCssParser *parser)
g_array_free (array, TRUE);
return value;
fail:
for (i = 0; i < array->len; i++)
{
gtk_css_filter_clear (&g_array_index (array, GtkCssFilter, i));
}
g_array_free (array, TRUE);
return NULL;
}
void
+19 -9
View File
@@ -230,14 +230,13 @@ gtk_css_font_features_value_parse (GtkCssParser *parser)
char *name;
int num;
if (_gtk_css_parser_try (parser, "normal", TRUE))
if (gtk_css_parser_try_ident (parser, "normal"))
return gtk_css_font_features_value_new_default ();
result = gtk_css_font_features_value_new_empty ();
do {
_gtk_css_parser_skip_whitespace (parser);
name = _gtk_css_parser_read_string (parser);
name = gtk_css_parser_consume_string (parser);
if (name == NULL)
{
_gtk_css_value_unref (result);
@@ -246,24 +245,35 @@ gtk_css_font_features_value_parse (GtkCssParser *parser)
if (!is_valid_opentype_tag (name))
{
_gtk_css_parser_error (parser, "Not a valid OpenType tag.");
gtk_css_parser_error_value (parser, "Not a valid OpenType tag.");
g_free (name);
_gtk_css_value_unref (result);
return NULL;
}
if (_gtk_css_parser_try (parser, "on", TRUE))
if (gtk_css_parser_try_ident (parser, "on"))
val = _gtk_css_number_value_new (1.0, GTK_CSS_NUMBER);
else if (_gtk_css_parser_try (parser, "off", TRUE))
else if (gtk_css_parser_try_ident (parser, "off"))
val = _gtk_css_number_value_new (0.0, GTK_CSS_NUMBER);
else if (_gtk_css_parser_try_int (parser, &num))
val = _gtk_css_number_value_new ((double)num, GTK_CSS_NUMBER);
else if (gtk_css_parser_has_integer (parser))
{
if (gtk_css_parser_consume_integer (parser, &num))
{
val = _gtk_css_number_value_new ((double)num, GTK_CSS_NUMBER);
}
else
{
g_free (name);
_gtk_css_value_unref (result);
return NULL;
}
}
else
val = _gtk_css_number_value_new (1.0, GTK_CSS_NUMBER);
gtk_css_font_features_value_add_feature (result, name, val);
g_free (name);
} while (_gtk_css_parser_try (parser, ",", TRUE));
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
return result;
}
+4 -5
View File
@@ -228,14 +228,13 @@ gtk_css_font_variations_value_parse (GtkCssParser *parser)
GtkCssValue *result, *coord;
char *name;
if (_gtk_css_parser_try (parser, "normal", TRUE))
if (gtk_css_parser_try_ident (parser, "normal"))
return gtk_css_font_variations_value_new_default ();
result = gtk_css_font_variations_value_new_empty ();
do {
_gtk_css_parser_skip_whitespace (parser);
name = _gtk_css_parser_read_string (parser);
name = gtk_css_parser_consume_string (parser);
if (name == NULL)
{
_gtk_css_value_unref (result);
@@ -244,7 +243,7 @@ gtk_css_font_variations_value_parse (GtkCssParser *parser)
if (!is_valid_opentype_tag (name))
{
_gtk_css_parser_error (parser, "Not a valid OpenType tag.");
gtk_css_parser_error_value (parser, "Not a valid OpenType tag.");
g_free (name);
_gtk_css_value_unref (result);
return NULL;
@@ -260,7 +259,7 @@ gtk_css_font_variations_value_parse (GtkCssParser *parser)
gtk_css_font_variations_value_add_axis (result, name, coord);
g_free (name);
} while (_gtk_css_parser_try (parser, ",", TRUE));
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
return result;
}
+1 -1
View File
@@ -150,7 +150,7 @@ gtk_css_icon_theme_value_parse (GtkCssParser *parser)
GtkCssValue *result;
char *s;
s = _gtk_css_parser_read_string (parser);
s = gtk_css_parser_consume_string (parser);
if (s == NULL)
return NULL;
+6 -3
View File
@@ -502,17 +502,20 @@ gtk_css_image_get_parser_type (GtkCssParser *parser)
{ "repeating-linear-gradient", _gtk_css_image_linear_get_type },
{ "radial-gradient", _gtk_css_image_radial_get_type },
{ "repeating-radial-gradient", _gtk_css_image_radial_get_type },
{ "cross-fade", _gtk_css_image_cross_fade_get_type },
{ "cross-fade", gtk_css_image_cross_fade_get_type },
{ "image", _gtk_css_image_fallback_get_type }
};
guint i;
for (i = 0; i < G_N_ELEMENTS (image_types); i++)
{
if (_gtk_css_parser_has_prefix (parser, image_types[i].prefix))
if (gtk_css_parser_has_function (parser, image_types[i].prefix))
return image_types[i].type_func ();
}
if (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_URL))
return _gtk_css_image_url_get_type ();
return G_TYPE_INVALID;
}
@@ -545,7 +548,7 @@ _gtk_css_image_new_parse (GtkCssParser *parser)
image_type = gtk_css_image_get_parser_type (parser);
if (image_type == G_TYPE_INVALID)
{
_gtk_css_parser_error (parser, "Not a valid image");
gtk_css_parser_error_syntax (parser, "Not a valid image");
return NULL;
}
+2 -2
View File
@@ -457,9 +457,9 @@ static gboolean
gtk_css_image_builtin_parse (GtkCssImage *image,
GtkCssParser *parser)
{
if (!_gtk_css_parser_try (parser, "builtin", TRUE))
if (!gtk_css_parser_try_ident (parser, "builtin"))
{
_gtk_css_parser_error (parser, "Expected 'builtin'");
gtk_css_parser_error_syntax (parser, "Expected 'builtin'");
return FALSE;
}
+299 -150
View File
@@ -26,64 +26,149 @@
#include "gtkcssnumbervalueprivate.h"
G_DEFINE_TYPE (GtkCssImageCrossFade, _gtk_css_image_cross_fade, GTK_TYPE_CSS_IMAGE)
typedef struct _CrossFadeEntry CrossFadeEntry;
struct _CrossFadeEntry
{
double progress;
gboolean has_progress;
GtkCssImage *image;
};
G_DEFINE_TYPE (GtkCssImageCrossFade, gtk_css_image_cross_fade, GTK_TYPE_CSS_IMAGE)
static void
cross_fade_entry_clear (gpointer data)
{
CrossFadeEntry *entry = data;
g_clear_object (&entry->image);
}
static void
gtk_css_image_cross_fade_recalculate_progress (GtkCssImageCrossFade *self)
{
double total_progress;
guint n_no_progress;
guint i;
total_progress = 0.0;
n_no_progress = 0;
for (i = 0; i < self->images->len; i++)
{
CrossFadeEntry *entry = &g_array_index (self->images, CrossFadeEntry, i);
if (entry->has_progress)
total_progress += entry->progress;
else
n_no_progress++;
}
if (n_no_progress)
{
double progress;
if (total_progress >= 1.0)
{
progress = 0.0;
}
else
{
progress = (1.0 - total_progress) / n_no_progress;
total_progress = 1.0;
}
for (i = 0; i < self->images->len; i++)
{
CrossFadeEntry *entry = &g_array_index (self->images, CrossFadeEntry, i);
if (!entry->has_progress)
entry->progress = progress;
}
}
self->total_progress = total_progress;
}
static void
gtk_css_image_cross_fade_add (GtkCssImageCrossFade *self,
gboolean has_progress,
double progress,
GtkCssImage *image)
{
CrossFadeEntry entry;
entry.has_progress = has_progress;
entry.progress = progress;
entry.image = image;
g_array_append_val (self->images, entry);
gtk_css_image_cross_fade_recalculate_progress (self);
}
static GtkCssImageCrossFade *
gtk_css_image_cross_fade_new_empty (void)
{
return g_object_new (GTK_TYPE_CSS_IMAGE_CROSS_FADE, NULL);
}
/* XXX: The following is not correct, it should actually run the
* CSS sizing algorithm for every child, not just query height and
* width independently.
*/
static int
gtk_css_image_cross_fade_get_width (GtkCssImage *image)
{
GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);
int start_width, end_width;
GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image);
double sum_width, sum_progress;
guint i;
if (cross_fade->start)
sum_width = 0.0;
sum_progress = 0.0;
for (i = 0; i < self->images->len; i++)
{
start_width = _gtk_css_image_get_width (cross_fade->start);
/* no intrinsic width, what now? */
if (start_width == 0)
return 0;
}
else
start_width = 0;
CrossFadeEntry *entry = &g_array_index (self->images, CrossFadeEntry, i);
int image_width;
if (cross_fade->end)
{
end_width = _gtk_css_image_get_width (cross_fade->end);
/* no intrinsic width, what now? */
if (end_width == 0)
return 0;
image_width = _gtk_css_image_get_width (entry->image);
if (image_width == 0)
continue;
sum_width += image_width * entry->progress;
sum_progress += entry->progress;
}
else
end_width = 0;
return start_width + (end_width - start_width) * cross_fade->progress;
if (sum_progress <= 0.0)
return 0;
return ceil (sum_width / sum_progress);
}
static int
gtk_css_image_cross_fade_get_height (GtkCssImage *image)
{
GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);
int start_height, end_height;
GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image);
double sum_height, sum_progress;
guint i;
if (cross_fade->start)
sum_height = 0.0;
sum_progress = 0.0;
for (i = 0; i < self->images->len; i++)
{
start_height = _gtk_css_image_get_height (cross_fade->start);
/* no intrinsic height, what now? */
if (start_height == 0)
return 0;
}
else
start_height = 0;
CrossFadeEntry *entry = &g_array_index (self->images, CrossFadeEntry, i);
int image_height;
if (cross_fade->end)
{
end_height = _gtk_css_image_get_height (cross_fade->end);
/* no intrinsic height, what now? */
if (end_height == 0)
return 0;
image_height = _gtk_css_image_get_height (entry->image);
if (image_height == 0)
continue;
sum_height += image_height * entry->progress;
sum_progress += entry->progress;
}
else
end_height = 0;
return start_height + (end_height - start_height) * cross_fade->progress;
if (sum_progress <= 0.0)
return 0;
return ceil (sum_height / sum_progress);
}
static gboolean
@@ -92,45 +177,62 @@ gtk_css_image_cross_fade_equal (GtkCssImage *image1,
{
GtkCssImageCrossFade *cross_fade1 = GTK_CSS_IMAGE_CROSS_FADE (image1);
GtkCssImageCrossFade *cross_fade2 = GTK_CSS_IMAGE_CROSS_FADE (image2);
guint i;
return cross_fade1->progress == cross_fade2->progress &&
_gtk_css_image_equal (cross_fade1->start, cross_fade2->start) &&
_gtk_css_image_equal (cross_fade1->end, cross_fade2->end);
if (cross_fade1->images->len != cross_fade2->images->len)
return FALSE;
for (i = 0; i < cross_fade1->images->len; i++)
{
CrossFadeEntry *entry1 = &g_array_index (cross_fade1->images, CrossFadeEntry, i);
CrossFadeEntry *entry2 = &g_array_index (cross_fade2->images, CrossFadeEntry, i);
if (entry1->progress != entry2->progress ||
!_gtk_css_image_equal (entry1->image, entry2->image))
return FALSE;
}
return TRUE;
}
static gboolean
gtk_css_image_cross_fade_is_dynamic (GtkCssImage *image)
{
GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);
GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image);
guint i;
return (cross_fade->start && gtk_css_image_is_dynamic (cross_fade->start))
|| (cross_fade->end && gtk_css_image_is_dynamic (cross_fade->end));
for (i = 0; i < self->images->len; i++)
{
CrossFadeEntry *entry = &g_array_index (self->images, CrossFadeEntry, i);
if (gtk_css_image_is_dynamic (entry->image))
return TRUE;
}
return FALSE;
}
static GtkCssImage *
gtk_css_image_cross_fade_get_dynamic_image (GtkCssImage *image,
gint64 monotonic_time)
{
GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);
GtkCssImage *start, *end, *result;
GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image);
GtkCssImageCrossFade *result;
guint i;
if (cross_fade->start)
start = gtk_css_image_get_dynamic_image (cross_fade->start, monotonic_time);
else
start = NULL;
if (cross_fade->end)
end = gtk_css_image_get_dynamic_image (cross_fade->end, monotonic_time);
else
end = NULL;
result = gtk_css_image_cross_fade_new_empty ();
result = _gtk_css_image_cross_fade_new (start, end, cross_fade->progress);
for (i = 0; i < self->images->len; i++)
{
CrossFadeEntry *entry = &g_array_index (self->images, CrossFadeEntry, i);
if (start)
g_object_unref (start);
if (end)
g_object_unref (end);
gtk_css_image_cross_fade_add (result,
entry->has_progress,
entry->progress,
gtk_css_image_get_dynamic_image (entry->image, monotonic_time));
}
return result;
return GTK_CSS_IMAGE (result);
}
static void
@@ -139,91 +241,140 @@ gtk_css_image_cross_fade_snapshot (GtkCssImage *image,
double width,
double height)
{
GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);
GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image);
double remaining;
guint i, n_cross_fades;
gtk_snapshot_push_cross_fade (snapshot, cross_fade->progress);
if (self->total_progress < 1.0)
{
n_cross_fades = self->images->len;
remaining = 1.0;
}
else
{
n_cross_fades = self->images->len - 1;
remaining = self->total_progress;
}
if (cross_fade->start)
gtk_css_image_snapshot (cross_fade->start, snapshot, width, height);
gtk_snapshot_pop (snapshot);
for (i = 0; i < n_cross_fades; i++)
{
CrossFadeEntry *entry = &g_array_index (self->images, CrossFadeEntry, i);
if (cross_fade->end)
gtk_css_image_snapshot (cross_fade->end, snapshot, width, height);
gtk_snapshot_pop (snapshot);
gtk_snapshot_push_cross_fade (snapshot, 1.0 - entry->progress / remaining);
remaining -= entry->progress;
gtk_css_image_snapshot (entry->image, snapshot, width, height);
gtk_snapshot_pop (snapshot);
}
if (n_cross_fades < self->images->len)
{
CrossFadeEntry *entry = &g_array_index (self->images, CrossFadeEntry, self->images->len - 1);
gtk_css_image_snapshot (entry->image, snapshot, width, height);
}
for (i = 0; i < n_cross_fades; i++)
{
gtk_snapshot_pop (snapshot);
}
}
static gboolean
gtk_css_image_cross_fade_parse (GtkCssImage *image,
GtkCssParser *parser)
parse_progress (GtkCssParser *parser,
gpointer option_data,
gpointer user_data)
{
GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);
if (!_gtk_css_parser_try (parser, "cross-fade(", TRUE))
{
_gtk_css_parser_error (parser, "Expected 'cross-fade('");
return FALSE;
}
if (gtk_css_number_value_can_parse (parser))
{
GtkCssValue *number;
number = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY);
if (number == NULL)
return FALSE;
cross_fade->progress = _gtk_css_number_value_get (number, 1);
_gtk_css_value_unref (number);
if (cross_fade->progress > 1.0)
{
_gtk_css_parser_error (parser, "Percentages over 100%% are not allowed");
return FALSE;
}
}
else
cross_fade->progress = 0.5;
cross_fade->end = _gtk_css_image_new_parse (parser);
if (cross_fade->end == NULL)
double *progress = option_data;
GtkCssValue *number;
number = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY);
if (number == NULL)
return FALSE;
*progress = _gtk_css_number_value_get (number, 1);
_gtk_css_value_unref (number);
if (_gtk_css_parser_try (parser, ",", TRUE))
if (*progress > 1.0)
{
/* XXX: allow parsing colors here */
cross_fade->start = _gtk_css_image_new_parse (parser);
if (cross_fade->start == NULL)
return FALSE;
}
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_parser_error (parser, "Missing closing bracket");
gtk_css_parser_error_value (parser, "Percentages over 100%% are not allowed");
return FALSE;
}
return TRUE;
}
static gboolean
parse_image (GtkCssParser *parser,
gpointer option_data,
gpointer user_data)
{
GtkCssImage **image = option_data;
*image = _gtk_css_image_new_parse (parser);
if (*image == NULL)
return FALSE;
return TRUE;
}
static guint
gtk_css_image_cross_fade_parse_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
GtkCssImageCrossFade *self = data;
double progress = -1.0;
GtkCssImage *image = NULL;
GtkCssParseOption options[] =
{
{ (void *) gtk_css_number_value_can_parse, parse_progress, &progress },
{ NULL, parse_image, &image },
};
if (!gtk_css_parser_consume_any (parser, options, G_N_ELEMENTS (options), self))
return 0;
g_assert (image != NULL);
if (progress < 0.0)
gtk_css_image_cross_fade_add (self, FALSE, 0.0, image);
else
gtk_css_image_cross_fade_add (self, TRUE, progress, image);
return 1;
}
static gboolean
gtk_css_image_cross_fade_parse (GtkCssImage *image,
GtkCssParser *parser)
{
if (!gtk_css_parser_has_function (parser, "cross-fade"))
{
gtk_css_parser_error_syntax (parser, "Expected 'cross-fade('");
return FALSE;
}
return gtk_css_parser_consume_function (parser, 1, G_MAXUINT, gtk_css_image_cross_fade_parse_arg, image);
}
static void
gtk_css_image_cross_fade_print (GtkCssImage *image,
GString *string)
{
GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);
GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image);
guint i;
g_string_append (string, "cross-fade(");
if (cross_fade->progress != 0.5)
for (i = 0; i < self->images->len; i++)
{
g_string_append_printf (string, "%g%% ", cross_fade->progress * 100.0);
CrossFadeEntry *entry = &g_array_index (self->images, CrossFadeEntry, i);
if (i > 0)
g_string_append_printf (string, ", ");
if (entry->has_progress)
g_string_append_printf (string, "%g%% ", entry->progress * 100.0);
_gtk_css_image_print (entry->image, string);
}
if (cross_fade->end)
_gtk_css_image_print (cross_fade->end, string);
else
g_string_append (string, "none");
if (cross_fade->start)
{
g_string_append (string, ", ");
_gtk_css_image_print (cross_fade->start, string);
}
g_string_append (string, ")");
}
@@ -234,26 +385,23 @@ gtk_css_image_cross_fade_compute (GtkCssImage *image,
GtkCssStyle *style,
GtkCssStyle *parent_style)
{
GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (image);
GtkCssImage *start, *end, *computed;
GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image);
GtkCssImageCrossFade *result;
guint i;
if (cross_fade->start)
start = _gtk_css_image_compute (cross_fade->start, property_id, provider, style, parent_style);
else
start = NULL;
if (cross_fade->end)
end = _gtk_css_image_compute (cross_fade->end, property_id, provider, style, parent_style);
else
end = NULL;
result = gtk_css_image_cross_fade_new_empty ();
computed = _gtk_css_image_cross_fade_new (start, end, cross_fade->progress);
for (i = 0; i < self->images->len; i++)
{
CrossFadeEntry *entry = &g_array_index (self->images, CrossFadeEntry, i);
if (start)
g_object_unref (start);
if (end)
g_object_unref (end);
gtk_css_image_cross_fade_add (result,
entry->has_progress,
entry->progress,
_gtk_css_image_compute (entry->image, property_id, provider, style, parent_style));
}
return computed;
return GTK_CSS_IMAGE (result);
}
static void
@@ -261,14 +409,13 @@ gtk_css_image_cross_fade_dispose (GObject *object)
{
GtkCssImageCrossFade *cross_fade = GTK_CSS_IMAGE_CROSS_FADE (object);
g_clear_object (&cross_fade->start);
g_clear_object (&cross_fade->end);
g_clear_pointer (&cross_fade->images, g_array_unref);
G_OBJECT_CLASS (_gtk_css_image_cross_fade_parent_class)->dispose (object);
G_OBJECT_CLASS (gtk_css_image_cross_fade_parent_class)->dispose (object);
}
static void
_gtk_css_image_cross_fade_class_init (GtkCssImageCrossFadeClass *klass)
gtk_css_image_cross_fade_class_init (GtkCssImageCrossFadeClass *klass)
{
GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -287,8 +434,10 @@ _gtk_css_image_cross_fade_class_init (GtkCssImageCrossFadeClass *klass)
}
static void
_gtk_css_image_cross_fade_init (GtkCssImageCrossFade *image_cross_fade)
gtk_css_image_cross_fade_init (GtkCssImageCrossFade *self)
{
self->images = g_array_new (FALSE, FALSE, sizeof (CrossFadeEntry));
g_array_set_clear_func (self->images, cross_fade_entry_clear);
}
GtkCssImage *
@@ -296,18 +445,18 @@ _gtk_css_image_cross_fade_new (GtkCssImage *start,
GtkCssImage *end,
double progress)
{
GtkCssImageCrossFade *cross_fade;
GtkCssImageCrossFade *self;
g_return_val_if_fail (start == NULL || GTK_IS_CSS_IMAGE (start), NULL);
g_return_val_if_fail (end == NULL || GTK_IS_CSS_IMAGE (end), NULL);
cross_fade = g_object_new (GTK_TYPE_CSS_IMAGE_CROSS_FADE, NULL);
if (start)
cross_fade->start = g_object_ref (start);
if (end)
cross_fade->end = g_object_ref (end);
cross_fade->progress = progress;
self = gtk_css_image_cross_fade_new_empty ();
return GTK_CSS_IMAGE (cross_fade);
if (start)
gtk_css_image_cross_fade_add (self, TRUE, 1.0 - progress, g_object_ref (start));
if (end)
gtk_css_image_cross_fade_add (self, TRUE, progress, g_object_ref (end));
return GTK_CSS_IMAGE (self);
}
+4 -5
View File
@@ -24,7 +24,7 @@
G_BEGIN_DECLS
#define GTK_TYPE_CSS_IMAGE_CROSS_FADE (_gtk_css_image_cross_fade_get_type ())
#define GTK_TYPE_CSS_IMAGE_CROSS_FADE (gtk_css_image_cross_fade_get_type ())
#define GTK_CSS_IMAGE_CROSS_FADE(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_IMAGE_CROSS_FADE, GtkCssImageCrossFade))
#define GTK_CSS_IMAGE_CROSS_FADE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_IMAGE_CROSS_FADE, GtkCssImageCrossFadeClass))
#define GTK_IS_CSS_IMAGE_CROSS_FADE(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_IMAGE_CROSS_FADE))
@@ -38,9 +38,8 @@ struct _GtkCssImageCrossFade
{
GtkCssImage parent;
GtkCssImage *start;
GtkCssImage *end;
double progress;
GArray *images;
double total_progress;
};
struct _GtkCssImageCrossFadeClass
@@ -48,7 +47,7 @@ struct _GtkCssImageCrossFadeClass
GtkCssImageClass parent_class;
};
GType _gtk_css_image_cross_fade_get_type (void) G_GNUC_CONST;
GType gtk_css_image_cross_fade_get_type (void) G_GNUC_CONST;
GtkCssImage * _gtk_css_image_cross_fade_new (GtkCssImage *start,
GtkCssImage *end,
+49 -38
View File
@@ -175,57 +175,68 @@ gtk_css_image_fallback_compute (GtkCssImage *image,
return GTK_CSS_IMAGE (g_object_ref (fallback));
}
typedef struct
{
GtkCssValue *color;
GPtrArray *images;
} ParseData;
static guint
gtk_css_image_fallback_parse_arg (GtkCssParser *parser,
guint arg,
gpointer _data)
{
ParseData *data = _data;
if (data->color != NULL)
{
gtk_css_parser_error_syntax (parser, "The color must be the last parameter");
return 0;
}
else if (_gtk_css_image_can_parse (parser))
{
GtkCssImage *image = _gtk_css_image_new_parse (parser);
if (image == NULL)
return 0;
g_ptr_array_add (data->images, image);
return 1;
}
else
{
data->color = _gtk_css_color_value_parse (parser);
if (data->color == NULL)
return 0;
return 1;
}
}
static gboolean
gtk_css_image_fallback_parse (GtkCssImage *image,
GtkCssParser *parser)
{
GtkCssImageFallback *fallback = GTK_CSS_IMAGE_FALLBACK (image);
GPtrArray *images;
GtkCssImage *child;
GtkCssImageFallback *self = GTK_CSS_IMAGE_FALLBACK (image);
ParseData data = { NULL, NULL };
if (!_gtk_css_parser_try (parser, "image", TRUE))
if (!gtk_css_parser_has_function (parser, "image"))
{
_gtk_css_parser_error (parser, "'image'");
gtk_css_parser_error_syntax (parser, "Expected 'image('");
return FALSE;
}
if (!_gtk_css_parser_try (parser, "(", TRUE))
data.images = g_ptr_array_new_with_free_func (g_object_unref);
if (!gtk_css_parser_consume_function (parser, 1, G_MAXUINT, gtk_css_image_fallback_parse_arg, &data))
{
_gtk_css_parser_error (parser,
"Expected '(' after 'image'");
g_clear_pointer (&data.color, _gtk_css_value_unref);
g_ptr_array_free (data.images, TRUE);
return FALSE;
}
images = g_ptr_array_new_with_free_func (g_object_unref);
do
{
child = NULL;
if (_gtk_css_image_can_parse (parser))
child = _gtk_css_image_new_parse (parser);
if (child == NULL)
{
fallback->color = _gtk_css_color_value_parse (parser);
if (fallback->color)
break;
g_ptr_array_free (images, TRUE);
return FALSE;
}
g_ptr_array_add (images, child);
}
while ( _gtk_css_parser_try (parser, ",", TRUE));
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
g_ptr_array_free (images, TRUE);
_gtk_css_parser_error (parser,
"Expected ')' at end of 'image'");
return FALSE;
}
fallback->n_images = images->len;
fallback->images = (GtkCssImage **) g_ptr_array_free (images, FALSE);
self->color = data.color;
self->n_images = data.images->len;
self->images = (GtkCssImage **) g_ptr_array_free (data.images, FALSE);
return TRUE;
}
+16 -15
View File
@@ -126,30 +126,31 @@ gtk_css_image_icon_theme_snapshot (GtkCssImage *image,
gtk_snapshot_pop (snapshot);
}
static guint
gtk_css_image_icon_theme_parse_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
GtkCssImageIconTheme *icon_theme = data;
icon_theme->name = gtk_css_parser_consume_string (parser);
if (icon_theme->name == NULL)
return 0;
return 1;
}
static gboolean
gtk_css_image_icon_theme_parse (GtkCssImage *image,
GtkCssParser *parser)
{
GtkCssImageIconTheme *icon_theme = GTK_CSS_IMAGE_ICON_THEME (image);
if (!_gtk_css_parser_try (parser, "-gtk-icontheme(", TRUE))
if (!gtk_css_parser_has_function (parser, "-gtk-icontheme"))
{
_gtk_css_parser_error (parser, "Expected '-gtk-icontheme('");
gtk_css_parser_error_syntax (parser, "Expected '-gtk-icontheme('");
return FALSE;
}
icon_theme->name = _gtk_css_parser_read_string (parser);
if (icon_theme->name == NULL)
return FALSE;
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_parser_error (parser, "Missing closing bracket at end of '-gtk-icontheme'");
return FALSE;
}
return TRUE;
return gtk_css_parser_consume_function (parser, 1, 1, gtk_css_image_icon_theme_parse_arg, image);
}
static void
+86 -78
View File
@@ -254,61 +254,80 @@ gtk_css_image_linear_snapshot (GtkCssImage *image,
}
}
static gboolean
gtk_css_image_linear_parse (GtkCssImage *image,
GtkCssParser *parser)
static guint
gtk_css_image_linear_parse_color_stop (GtkCssImageLinear *self,
GtkCssParser *parser)
{
GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
guint i;
GtkCssImageLinearColorStop stop;
if (_gtk_css_parser_try (parser, "repeating-linear-gradient(", TRUE))
linear->repeating = TRUE;
else if (_gtk_css_parser_try (parser, "linear-gradient(", TRUE))
linear->repeating = FALSE;
stop.color = _gtk_css_color_value_parse (parser);
if (stop.color == NULL)
return 0;
if (gtk_css_number_value_can_parse (parser))
{
stop.offset = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_PERCENT
| GTK_CSS_PARSE_LENGTH);
if (stop.offset == NULL)
{
_gtk_css_value_unref (stop.color);
return 0;
}
}
else
{
_gtk_css_parser_error (parser, "Not a linear gradient");
return FALSE;
stop.offset = NULL;
}
if (_gtk_css_parser_try (parser, "to", TRUE))
g_array_append_val (self->stops, stop);
return 1;
}
static guint
gtk_css_image_linear_parse_first_arg (GtkCssImageLinear *linear,
GtkCssParser *parser)
{
guint i;
if (gtk_css_parser_try_ident (parser, "to"))
{
for (i = 0; i < 2; i++)
{
if (_gtk_css_parser_try (parser, "left", TRUE))
if (gtk_css_parser_try_ident (parser, "left"))
{
if (linear->side & ((1 << GTK_CSS_LEFT) | (1 << GTK_CSS_RIGHT)))
{
_gtk_css_parser_error (parser, "Expected 'top', 'bottom' or comma");
return FALSE;
gtk_css_parser_error_syntax (parser, "Expected 'top', 'bottom' or comma");
return 0;
}
linear->side |= (1 << GTK_CSS_LEFT);
}
else if (_gtk_css_parser_try (parser, "right", TRUE))
else if (gtk_css_parser_try_ident (parser, "right"))
{
if (linear->side & ((1 << GTK_CSS_LEFT) | (1 << GTK_CSS_RIGHT)))
{
_gtk_css_parser_error (parser, "Expected 'top', 'bottom' or comma");
return FALSE;
gtk_css_parser_error_syntax (parser, "Expected 'top', 'bottom' or comma");
return 0;
}
linear->side |= (1 << GTK_CSS_RIGHT);
}
else if (_gtk_css_parser_try (parser, "top", TRUE))
else if (gtk_css_parser_try_ident (parser, "top"))
{
if (linear->side & ((1 << GTK_CSS_TOP) | (1 << GTK_CSS_BOTTOM)))
{
_gtk_css_parser_error (parser, "Expected 'left', 'right' or comma");
return FALSE;
gtk_css_parser_error_syntax (parser, "Expected 'left', 'right' or comma");
return 0;
}
linear->side |= (1 << GTK_CSS_TOP);
}
else if (_gtk_css_parser_try (parser, "bottom", TRUE))
else if (gtk_css_parser_try_ident (parser, "bottom"))
{
if (linear->side & ((1 << GTK_CSS_TOP) | (1 << GTK_CSS_BOTTOM)))
{
_gtk_css_parser_error (parser, "Expected 'left', 'right' or comma");
return FALSE;
gtk_css_parser_error_syntax (parser, "Expected 'left', 'right' or comma");
return 0;
}
linear->side |= (1 << GTK_CSS_BOTTOM);
}
@@ -318,72 +337,61 @@ gtk_css_image_linear_parse (GtkCssImage *image,
if (linear->side == 0)
{
_gtk_css_parser_error (parser, "Expected side that gradient should go to");
return FALSE;
gtk_css_parser_error_syntax (parser, "Expected side that gradient should go to");
return 0;
}
if (!_gtk_css_parser_try (parser, ",", TRUE))
{
_gtk_css_parser_error (parser, "Expected a comma");
return FALSE;
}
return 1;
}
else if (gtk_css_number_value_can_parse (parser))
{
linear->angle = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (linear->angle == NULL)
return FALSE;
if (!_gtk_css_parser_try (parser, ",", TRUE))
{
_gtk_css_parser_error (parser, "Expected a comma");
return FALSE;
}
return 0;
return 1;
}
else
linear->side = 1 << GTK_CSS_BOTTOM;
do {
GtkCssImageLinearColorStop stop;
stop.color = _gtk_css_color_value_parse (parser);
if (stop.color == NULL)
return FALSE;
if (gtk_css_number_value_can_parse (parser))
{
stop.offset = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_PERCENT
| GTK_CSS_PARSE_LENGTH);
if (stop.offset == NULL)
{
_gtk_css_value_unref (stop.color);
return FALSE;
}
}
else
{
stop.offset = NULL;
}
g_array_append_val (linear->stops, stop);
} while (_gtk_css_parser_try (parser, ",", TRUE));
if (linear->stops->len < 2)
{
_gtk_css_parser_error (parser, "%s() needs at least 2 color stops.",
linear->repeating ? "repeating-linear-gradient" : "linear-gradient");
linear->side = 1 << GTK_CSS_BOTTOM;
if (!gtk_css_image_linear_parse_color_stop (linear, parser))
return 0;
return 2;
}
}
static guint
gtk_css_image_linear_parse_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
GtkCssImageLinear *self = data;
if (arg == 0)
return gtk_css_image_linear_parse_first_arg (self, parser);
else
return gtk_css_image_linear_parse_color_stop (self, parser);
}
static gboolean
gtk_css_image_linear_parse (GtkCssImage *image,
GtkCssParser *parser)
{
GtkCssImageLinear *self = GTK_CSS_IMAGE_LINEAR (image);
if (gtk_css_parser_has_function (parser, "repeating-linear-gradient"))
self->repeating = TRUE;
else if (gtk_css_parser_has_function (parser, "linear-gradient"))
self->repeating = FALSE;
else
{
gtk_css_parser_error_syntax (parser, "Not a linear gradient");
return FALSE;
}
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_parser_error (parser, "Missing closing bracket at end of linear gradient");
return FALSE;
}
return TRUE;
return gtk_css_parser_consume_function (parser, 3, G_MAXUINT, gtk_css_image_linear_parse_arg, self);
}
static void
+93 -74
View File
@@ -233,11 +233,41 @@ gtk_css_image_radial_snapshot (GtkCssImage *image,
cairo_destroy (cr);
}
static gboolean
gtk_css_image_radial_parse (GtkCssImage *image,
GtkCssParser *parser)
static guint
gtk_css_image_radial_parse_color_stop (GtkCssImageRadial *radial,
GtkCssParser *parser)
{
GtkCssImageRadialColorStop stop;
stop.color = _gtk_css_color_value_parse (parser);
if (stop.color == NULL)
return 0;
if (gtk_css_number_value_can_parse (parser))
{
stop.offset = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_PERCENT
| GTK_CSS_PARSE_LENGTH);
if (stop.offset == NULL)
{
_gtk_css_value_unref (stop.color);
return 0;
}
}
else
{
stop.offset = NULL;
}
g_array_append_val (radial->stops, stop);
return 1;
}
static guint
gtk_css_image_radial_parse_first_arg (GtkCssImageRadial *radial,
GtkCssParser *parser)
{
GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
gboolean has_shape = FALSE;
gboolean has_size = FALSE;
gboolean found_one = FALSE;
@@ -252,24 +282,15 @@ gtk_css_image_radial_parse (GtkCssImage *image,
{ "farthest-corner", GTK_CSS_FARTHEST_CORNER }
};
if (_gtk_css_parser_try (parser, "repeating-radial-gradient(", TRUE))
radial->repeating = TRUE;
else if (_gtk_css_parser_try (parser, "radial-gradient(", TRUE))
radial->repeating = FALSE;
else
{
_gtk_css_parser_error (parser, "Not a radial gradient");
return FALSE;
}
found_one = FALSE;
do {
found_one = FALSE;
if (!has_shape && _gtk_css_parser_try (parser, "circle", TRUE))
if (!has_shape && gtk_css_parser_try_ident (parser, "circle"))
{
radial->circle = TRUE;
found_one = has_shape = TRUE;
}
else if (!has_shape && _gtk_css_parser_try (parser, "ellipse", TRUE))
else if (!has_shape && gtk_css_parser_try_ident (parser, "ellipse"))
{
radial->circle = FALSE;
found_one = has_shape = TRUE;
@@ -278,7 +299,7 @@ gtk_css_image_radial_parse (GtkCssImage *image,
{
for (i = 0; i < G_N_ELEMENTS (names); i++)
{
if (_gtk_css_parser_try (parser, names[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, names[i].name))
{
found_one = has_size = TRUE;
radial->size = names[i].value;
@@ -286,40 +307,39 @@ gtk_css_image_radial_parse (GtkCssImage *image,
}
}
if (!has_size)
if (!has_size && gtk_css_number_value_can_parse (parser))
{
radial->sizes[0] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH | GTK_CSS_PARSE_PERCENT);
if (radial->sizes[0] == NULL)
return 0;
if (gtk_css_number_value_can_parse (parser))
radial->sizes[0] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH | GTK_CSS_PARSE_PERCENT);
if (gtk_css_number_value_can_parse (parser))
radial->sizes[1] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH | GTK_CSS_PARSE_PERCENT);
found_one = has_size = radial->sizes[0] != NULL;
{
radial->sizes[1] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH | GTK_CSS_PARSE_PERCENT);
if (radial->sizes[1] == NULL)
return 0;
}
found_one = has_size = TRUE;
}
if (!has_size)
break;
}
else
{
break;
}
} while (!(has_shape && has_size));
} while (found_one && !(has_shape && has_size));
if (_gtk_css_parser_try (parser, "at", TRUE))
if (gtk_css_parser_try_ident (parser, "at"))
{
radial->position = _gtk_css_position_value_parse (parser);
if (!radial->position)
return FALSE;
if (!_gtk_css_parser_try (parser, ",", TRUE))
{
_gtk_css_parser_error (parser, "Expected a comma here");
return FALSE;
}
return 0;
found_one = TRUE;
}
else
{
radial->position = _gtk_css_position_value_new (_gtk_css_number_value_new (50, GTK_CSS_PERCENT),
_gtk_css_number_value_new (50, GTK_CSS_PERCENT));
if ((has_shape || has_size) &&
!_gtk_css_parser_try (parser, ",", TRUE))
{
_gtk_css_parser_error (parser, "Expected a comma here");
return FALSE;
}
}
if (!has_size)
@@ -339,14 +359,14 @@ gtk_css_image_radial_parse (GtkCssImage *image,
{
if (radial->sizes[0] && radial->sizes[1])
{
_gtk_css_parser_error (parser, "Circular gradient can only have one size");
return FALSE;
gtk_css_parser_error_syntax (parser, "Circular gradient can only have one size");
return 0;
}
if (radial->sizes[0] && gtk_css_number_value_has_percent (radial->sizes[0]))
{
_gtk_css_parser_error (parser, "Circular gradient cannot have percentage as size");
return FALSE;
gtk_css_parser_error_syntax (parser, "Circular gradient cannot have percentage as size");
return 0;
}
}
@@ -356,47 +376,46 @@ gtk_css_image_radial_parse (GtkCssImage *image,
radial->sizes[1] = _gtk_css_value_ref (radial->sizes[0]);
}
do {
GtkCssImageRadialColorStop stop;
if (found_one)
return 1;
stop.color = _gtk_css_color_value_parse (parser);
if (stop.color == NULL)
return FALSE;
if (!gtk_css_image_radial_parse_color_stop (radial, parser))
return 0;
if (gtk_css_number_value_can_parse (parser))
{
stop.offset = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_PERCENT
| GTK_CSS_PARSE_LENGTH);
if (stop.offset == NULL)
{
_gtk_css_value_unref (stop.color);
return FALSE;
}
}
else
{
stop.offset = NULL;
}
return 2;
}
g_array_append_val (radial->stops, stop);
static guint
gtk_css_image_radial_parse_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
GtkCssImageRadial *self = data;
} while (_gtk_css_parser_try (parser, ",", TRUE));
if (arg == 0)
return gtk_css_image_radial_parse_first_arg (self, parser);
else
return gtk_css_image_radial_parse_color_stop (self, parser);
if (radial->stops->len < 2)
}
static gboolean
gtk_css_image_radial_parse (GtkCssImage *image,
GtkCssParser *parser)
{
GtkCssImageRadial *self = GTK_CSS_IMAGE_RADIAL (image);
if (gtk_css_parser_has_function (parser, "repeating-radial-gradient"))
self->repeating = TRUE;
else if (gtk_css_parser_has_function (parser, "radial-gradient"))
self->repeating = FALSE;
else
{
_gtk_css_parser_error (parser, "%s() needs at least 2 color stops.",
radial->repeating ? "repeating-radial-gradient" : "radial-gradient");
gtk_css_parser_error_syntax (parser, "Not a radial gradient");
return FALSE;
}
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_parser_error (parser, "Missing closing bracket at end of radial gradient");
return FALSE;
}
return TRUE;
return gtk_css_parser_consume_function (parser, 3, G_MAXUINT, gtk_css_image_radial_parse_arg, self);
}
static void
+33 -38
View File
@@ -155,8 +155,8 @@ gtk_css_image_recolor_load (GtkCssImageRecolor *recolor,
uri = g_file_get_uri (recolor->file);
g_set_error (gerror,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_FAILED,
GTK_CSS_PARSER_ERROR,
GTK_CSS_PARSER_ERROR_FAILED,
"Error loading image '%s': %s", uri, local_error->message);
g_free (uri);
}
@@ -235,49 +235,44 @@ gtk_css_image_recolor_compute (GtkCssImage *image,
return img;
}
static guint
gtk_css_image_recolor_parse_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
GtkCssImageRecolor *self = data;
switch (arg)
{
case 0:
self->file = gtk_css_parser_consume_url (parser);
if (self->file == NULL)
return 0;
return 1;
case 1:
self->palette = gtk_css_palette_value_parse (parser);
if (self->palette == NULL)
return 0;
return 1;
default:
g_assert_not_reached ();
return 0;
}
}
static gboolean
gtk_css_image_recolor_parse (GtkCssImage *image,
GtkCssParser *parser)
GtkCssParser *parser)
{
GtkCssImageRecolor *recolor = GTK_CSS_IMAGE_RECOLOR (image);
if (!_gtk_css_parser_try (parser, "-gtk-recolor", TRUE))
if (!gtk_css_parser_has_function (parser, "-gtk-recolor"))
{
_gtk_css_parser_error (parser, "'-gtk-recolor'");
gtk_css_parser_error_syntax (parser, "Expected '-gtk-recolor('");
return FALSE;
}
if (!_gtk_css_parser_try (parser, "(", TRUE))
{
_gtk_css_parser_error (parser, "Expected '(' after '-gtk-recolor'");
return FALSE;
}
recolor->file = _gtk_css_parser_read_url (parser);
if (recolor->file == NULL)
{
_gtk_css_parser_error (parser, "Expected a url here");
return FALSE;
}
if ( _gtk_css_parser_try (parser, ",", TRUE))
{
recolor->palette = gtk_css_palette_value_parse (parser);
if (recolor->palette == NULL)
{
_gtk_css_parser_error (parser, "A palette is required here");
return FALSE;
}
}
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_parser_error (parser,
"Expected ')' at end of '-gtk-recolor'");
return FALSE;
}
return TRUE;
return gtk_css_parser_consume_function (parser, 1, 2, gtk_css_image_recolor_parse_arg, image);
}
static int
+42 -56
View File
@@ -143,76 +143,62 @@ gtk_css_image_scaled_compute (GtkCssImage *image,
return GTK_CSS_IMAGE (res);
}
typedef struct
{
GPtrArray *images;
GArray *scales;
} GtkCssImageScaledParseData;
static guint
gtk_css_image_scaled_parse_arg (GtkCssParser *parser,
guint arg,
gpointer data_)
{
GtkCssImageScaledParseData *data = data_;
GtkCssImage *child;
int scale;
child = _gtk_css_image_new_parse (parser);
if (child == NULL)
return 0;
if (!gtk_css_parser_has_integer (parser))
scale = arg > 0 ? g_array_index (data->scales, int, arg - 1) + 1 : 1;
else if (!gtk_css_parser_consume_integer (parser, &scale))
return 0;
g_ptr_array_add (data->images, child);
g_array_append_val (data->scales, scale);
return 1;
}
static gboolean
gtk_css_image_scaled_parse (GtkCssImage *image,
GtkCssParser *parser)
{
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (image);
GPtrArray *images;
GArray *scales;
int last_scale;
GtkCssImage *child;
GtkCssImageScaled *self = GTK_CSS_IMAGE_SCALED (image);
GtkCssImageScaledParseData data;
if (!_gtk_css_parser_try (parser, "-gtk-scaled", TRUE))
if (!gtk_css_parser_has_function (parser, "-gtk-scaled"))
{
_gtk_css_parser_error (parser, "'-gtk-scaled'");
gtk_css_parser_error_syntax (parser, "Expected '-gtk-scaled('");
return FALSE;
}
if (!_gtk_css_parser_try (parser, "(", TRUE))
data.images = g_ptr_array_new_with_free_func (g_object_unref);
data.scales = g_array_new (FALSE, FALSE, sizeof (int));
if (!gtk_css_parser_consume_function (parser, 1, G_MAXUINT, gtk_css_image_scaled_parse_arg, &data))
{
_gtk_css_parser_error (parser,
"Expected '(' after '-gtk-scaled'");
g_ptr_array_unref (data.images);
g_array_unref (data.scales);
return FALSE;
}
images = g_ptr_array_new_with_free_func (g_object_unref);
scales = g_array_new (FALSE, FALSE, sizeof (int));
last_scale = 0;
do
{
child = _gtk_css_image_new_parse (parser);
if (child == NULL)
{
g_ptr_array_free (images, TRUE);
g_array_free (scales, TRUE);
return FALSE;
}
g_ptr_array_add (images, child);
if (!_gtk_css_parser_try (parser, ",", TRUE))
{
last_scale += 1;
g_array_append_val (scales, last_scale);
break;
}
else if (_gtk_css_parser_try_int (parser, &last_scale))
{
g_array_append_val (scales, last_scale);
if (!_gtk_css_parser_try (parser, ",", TRUE))
break;
}
else
{
last_scale += 1;
g_array_append_val (scales, last_scale);
}
}
while (TRUE);
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
g_ptr_array_free (images, TRUE);
g_array_free (scales, TRUE);
_gtk_css_parser_error (parser,
"Expected ')' at end of '-gtk-scaled'");
return FALSE;
}
scaled->n_images = images->len;
scaled->images = (GtkCssImage **) g_ptr_array_free (images, FALSE);
scaled->scales = (int *) g_array_free (scales, FALSE);
self->n_images = data.images->len;
self->images = (GtkCssImage **) g_ptr_array_free (data.images, FALSE);
self->scales = (int *) g_array_free (data.scales, FALSE);
return TRUE;
}
+3 -3
View File
@@ -65,8 +65,8 @@ gtk_css_image_url_load_image (GtkCssImageUrl *url,
uri = g_file_get_uri (url->file);
g_set_error (error,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_FAILED,
GTK_CSS_PARSER_ERROR,
GTK_CSS_PARSER_ERROR_FAILED,
"Error loading image '%s': %s", uri, local_error->message);
g_free (uri);
}
@@ -165,7 +165,7 @@ gtk_css_image_url_parse (GtkCssImage *image,
{
GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image);
url->file = _gtk_css_parser_read_url (parser);
url->file = gtk_css_parser_consume_url (parser);
if (url->file == NULL)
return FALSE;
+32 -41
View File
@@ -215,40 +215,35 @@ keyframes_set_value (GtkCssKeyframes *keyframes,
}
static gboolean
parse_declaration (GtkCssKeyframes *keyframes,
guint k,
GtkCssParser *parser)
gtk_css_keyframes_parse_declaration (GtkCssKeyframes *keyframes,
guint k,
GtkCssParser *parser)
{
GtkStyleProperty *property;
GtkCssValue *value;
char *name;
while (_gtk_css_parser_try (parser, ";", TRUE))
{
/* SKIP ALL THE THINGS! */
}
name = _gtk_css_parser_try_ident (parser, TRUE);
name = gtk_css_parser_consume_ident (parser);
if (name == NULL)
{
_gtk_css_parser_error (parser, "No property name given");
if (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF))
gtk_css_parser_error_syntax (parser, "Expected a property name");
return FALSE;
}
property = _gtk_style_property_lookup (name);
if (property == NULL)
{
/* should be GTK_CSS_PROVIDER_ERROR_NAME */
_gtk_css_parser_error (parser, "No property named '%s'", name);
gtk_css_parser_error_value (parser, "No property named '%s'", name);
g_free (name);
return FALSE;
}
g_free (name);
if (!_gtk_css_parser_try (parser, ":", TRUE))
if (!gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COLON))
{
_gtk_css_parser_error (parser, "Expected a ':'");
gtk_css_parser_error_syntax (parser, "Expected a ':'");
return FALSE;
}
@@ -256,10 +251,9 @@ parse_declaration (GtkCssKeyframes *keyframes,
if (value == NULL)
return FALSE;
if (!_gtk_css_parser_try (parser, ";", TRUE) &&
!_gtk_css_parser_begins_with (parser, '}'))
if (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF))
{
_gtk_css_parser_error (parser, "Junk at end of value");
gtk_css_parser_error_syntax (parser, "Junk at end of value");
_gtk_css_value_unref (value);
return FALSE;
}
@@ -279,12 +273,12 @@ parse_declaration (GtkCssKeyframes *keyframes,
}
if (!animatable)
_gtk_css_parser_error (parser, "shorthand '%s' cannot be animated", _gtk_style_property_get_name (property));
gtk_css_parser_error_value (parser, "shorthand '%s' cannot be animated", _gtk_style_property_get_name (property));
}
else if (GTK_IS_CSS_STYLE_PROPERTY (property))
{
if (!keyframes_set_value (keyframes, k, GTK_CSS_STYLE_PROPERTY (property), value))
_gtk_css_parser_error (parser, "Cannot animate property '%s'", _gtk_style_property_get_name (property));
gtk_css_parser_error_value (parser, "Cannot animate property '%s'", _gtk_style_property_get_name (property));
}
else
{
@@ -297,28 +291,27 @@ parse_declaration (GtkCssKeyframes *keyframes,
}
static gboolean
parse_block (GtkCssKeyframes *keyframes,
guint k,
GtkCssParser *parser)
gtk_css_keyframes_parse_block (GtkCssKeyframes *keyframes,
guint k,
GtkCssParser *parser)
{
if (!_gtk_css_parser_try (parser, "{", TRUE))
if (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_OPEN_CURLY))
{
_gtk_css_parser_error (parser, "Expected closing bracket after keyframes block");
gtk_css_parser_error_syntax (parser, "Expected '{'");
return FALSE;
}
while (!_gtk_css_parser_try (parser, "}", TRUE))
{
if (!parse_declaration (keyframes, k, parser))
_gtk_css_parser_resync (parser, TRUE, '}');
gtk_css_parser_start_block (parser);
if (_gtk_css_parser_is_eof (parser))
{
_gtk_css_parser_error (parser, "Expected closing '}' after keyframes block");
return FALSE;
}
while (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF))
{
gtk_css_parser_start_semicolon_block (parser, GTK_CSS_TOKEN_EOF);
gtk_css_keyframes_parse_declaration (keyframes, k, parser);
gtk_css_parser_end_block (parser);
}
gtk_css_parser_end_block (parser);
return TRUE;
}
@@ -333,19 +326,18 @@ _gtk_css_keyframes_parse (GtkCssParser *parser)
keyframes = gtk_css_keyframes_new ();
while (!_gtk_css_parser_begins_with (parser, '}'))
while (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF))
{
if (_gtk_css_parser_try (parser, "from", TRUE))
if (gtk_css_parser_try_ident (parser, "from"))
progress = 0;
else if (_gtk_css_parser_try (parser, "to", TRUE))
else if (gtk_css_parser_try_ident (parser, "to"))
progress = 1;
else if (_gtk_css_parser_try_double (parser, &progress) &&
_gtk_css_parser_try (parser, "%", TRUE))
else if (gtk_css_parser_consume_percentage (parser, &progress))
{
if (progress < 0 || progress > 100)
{
/* XXX: should we skip over the block here? */
_gtk_css_parser_error (parser, "percentages must be between 0%% and 100%%");
gtk_css_parser_error_value (parser, "percentages must be between 0%% and 100%%");
_gtk_css_keyframes_unref (keyframes);
return NULL;
}
@@ -353,14 +345,13 @@ _gtk_css_keyframes_parse (GtkCssParser *parser)
}
else
{
_gtk_css_parser_error (parser, "expected a percentage");
_gtk_css_keyframes_unref (keyframes);
return NULL;
}
k = gtk_css_keyframes_add_keyframe (keyframes, progress);
if (!parse_block (keyframes, k, parser))
if (!gtk_css_keyframes_parse_block (keyframes, k, parser))
{
_gtk_css_keyframes_unref (keyframes);
return NULL;
+3 -1
View File
@@ -19,9 +19,11 @@
#define __GTK_CSS_LOOKUP_PRIVATE_H__
#include <glib-object.h>
#include "gtk/gtkbitmaskprivate.h"
#include "gtk/gtkcssstaticstyleprivate.h"
#include "gtk/gtkcsssection.h"
#include "gtk/css/gtkcsssection.h"
G_BEGIN_DECLS
-1
View File
@@ -20,7 +20,6 @@
#include "gtkcssnodeprivate.h"
#include "gtkcssanimatedstyleprivate.h"
#include "gtkcsssectionprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
+10 -3
View File
@@ -129,15 +129,22 @@ gtk_css_number_value_transition (GtkCssValue *start,
gboolean
gtk_css_number_value_can_parse (GtkCssParser *parser)
{
return _gtk_css_parser_has_number (parser)
|| _gtk_css_parser_has_prefix (parser, "calc");
return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SIGNED_NUMBER)
|| gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SIGNLESS_NUMBER)
|| gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SIGNED_INTEGER)
|| gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SIGNLESS_INTEGER)
|| gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_PERCENTAGE)
|| gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION)
|| gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION)
|| gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_DIMENSION)
|| gtk_css_parser_has_function (parser, "calc");
}
GtkCssValue *
_gtk_css_number_value_parse (GtkCssParser *parser,
GtkCssNumberParseFlags flags)
{
if (_gtk_css_parser_has_prefix (parser, "calc"))
if (gtk_css_parser_has_function (parser, "calc"))
return gtk_css_calc_value_parse (parser, flags);
return gtk_css_dimension_value_parse (parser, flags);
+3 -4
View File
@@ -216,16 +216,15 @@ gtk_css_palette_value_parse (GtkCssParser *parser)
GtkCssValue *result, *color;
char *ident;
if (_gtk_css_parser_try (parser, "default", TRUE))
if (gtk_css_parser_try_ident (parser, "default"))
return gtk_css_palette_value_new_default ();
result = gtk_css_palette_value_new_empty ();
do {
ident = _gtk_css_parser_try_ident (parser, TRUE);
ident = gtk_css_parser_consume_ident (parser);
if (ident == NULL)
{
_gtk_css_parser_error (parser, "expected color name");
_gtk_css_value_unref (result);
return NULL;
}
@@ -240,7 +239,7 @@ gtk_css_palette_value_parse (GtkCssParser *parser)
gtk_css_palette_value_add_color (result, ident, color);
g_free (ident);
} while (_gtk_css_parser_try (parser, ",", TRUE));
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
return result;
}
-902
View File
@@ -19,908 +19,6 @@
#include "gtkcssparserprivate.h"
#include "gtkcssdimensionvalueprivate.h"
#include <errno.h>
#include <string.h>
/* just for the errors, yay! */
#include "gtkcssprovider.h"
#define NEWLINE_CHARS "\r\n"
#define WHITESPACE_CHARS "\f \t"
#define NMSTART "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
#define NMCHAR NMSTART "01234567890-_"
#define URLCHAR NMCHAR "!#$%&*~"
#define GTK_IS_CSS_PARSER(parser) ((parser) != NULL)
struct _GtkCssParser
{
const char *data;
GFile *file;
GtkCssParserErrorFunc error_func;
gpointer user_data;
const char *line_start;
guint line;
/* Use this for parsing identifiers, names and strings. */
GString *ident_str;
};
GtkCssParser *
_gtk_css_parser_new (const char *data,
GFile *file,
GtkCssParserErrorFunc error_func,
gpointer user_data)
{
GtkCssParser *parser;
g_return_val_if_fail (data != NULL, NULL);
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
parser = g_slice_new0 (GtkCssParser);
parser->data = data;
if (file)
parser->file = g_object_ref (file);
parser->error_func = error_func;
parser->user_data = user_data;
parser->line_start = data;
parser->line = 0;
parser->ident_str = NULL;
return parser;
}
void
_gtk_css_parser_free (GtkCssParser *parser)
{
g_return_if_fail (GTK_IS_CSS_PARSER (parser));
if (parser->file)
g_object_unref (parser->file);
if (parser->ident_str)
g_string_free (parser->ident_str, TRUE);
g_slice_free (GtkCssParser, parser);
}
gboolean
_gtk_css_parser_is_eof (GtkCssParser *parser)
{
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), TRUE);
return *parser->data == 0;
}
gboolean
_gtk_css_parser_begins_with (GtkCssParser *parser,
char c)
{
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), TRUE);
return *parser->data == c;
}
gboolean
_gtk_css_parser_has_prefix (GtkCssParser *parser,
const char *prefix)
{
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
return g_ascii_strncasecmp (parser->data, prefix, strlen (prefix)) == 0;
}
guint
_gtk_css_parser_get_line (GtkCssParser *parser)
{
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), 1);
return parser->line;
}
guint
_gtk_css_parser_get_position (GtkCssParser *parser)
{
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), 1);
return parser->data - parser->line_start;
}
static GFile *
gtk_css_parser_get_base_file (GtkCssParser *parser)
{
GFile *base;
if (parser->file)
{
base = g_file_get_parent (parser->file);
}
else
{
char *dir = g_get_current_dir ();
base = g_file_new_for_path (dir);
g_free (dir);
}
return base;
}
GFile *
_gtk_css_parser_get_file_for_path (GtkCssParser *parser,
const char *path)
{
GFile *base, *file;
g_return_val_if_fail (parser != NULL, NULL);
g_return_val_if_fail (path != NULL, NULL);
base = gtk_css_parser_get_base_file (parser);
file = g_file_resolve_relative_path (base, path);
g_object_unref (base);
return file;
}
GFile *
_gtk_css_parser_get_file (GtkCssParser *parser)
{
g_return_val_if_fail (parser != NULL, NULL);
return parser->file;
}
void
_gtk_css_parser_take_error (GtkCssParser *parser,
GError *error)
{
parser->error_func (parser, error, parser->user_data);
g_error_free (error);
}
void
_gtk_css_parser_error (GtkCssParser *parser,
const char *format,
...)
{
GError *error;
va_list args;
va_start (args, format);
error = g_error_new_valist (GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
format, args);
va_end (args);
_gtk_css_parser_take_error (parser, error);
}
static gboolean
gtk_css_parser_new_line (GtkCssParser *parser)
{
gboolean result = FALSE;
if (*parser->data == '\r')
{
result = TRUE;
parser->data++;
}
if (*parser->data == '\n')
{
result = TRUE;
parser->data++;
}
if (result)
{
parser->line++;
parser->line_start = parser->data;
}
return result;
}
static gboolean
gtk_css_parser_skip_comment (GtkCssParser *parser)
{
if (parser->data[0] != '/' ||
parser->data[1] != '*')
return FALSE;
parser->data += 2;
while (*parser->data)
{
gsize len = strcspn (parser->data, NEWLINE_CHARS "/");
parser->data += len;
if (gtk_css_parser_new_line (parser))
continue;
parser->data++;
if (len > 0 && parser->data[-2] == '*')
return TRUE;
if (parser->data[0] == '*')
_gtk_css_parser_error (parser, "'/*' in comment block");
}
/* FIXME: position */
_gtk_css_parser_error (parser, "Unterminated comment");
return TRUE;
}
void
_gtk_css_parser_skip_whitespace (GtkCssParser *parser)
{
size_t len;
while (*parser->data)
{
if (gtk_css_parser_new_line (parser))
continue;
len = strspn (parser->data, WHITESPACE_CHARS);
if (len)
{
parser->data += len;
continue;
}
if (!gtk_css_parser_skip_comment (parser))
break;
}
}
gboolean
_gtk_css_parser_try (GtkCssParser *parser,
const char *string,
gboolean skip_whitespace)
{
gsize string_len;
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
g_return_val_if_fail (string != NULL, FALSE);
string_len = strlen (string);
if (g_ascii_strncasecmp (parser->data, string, string_len) != 0)
return FALSE;
parser->data += string_len;
if (skip_whitespace)
_gtk_css_parser_skip_whitespace (parser);
return TRUE;
}
static guint
get_xdigit (char c)
{
if (c >= 'a')
return c - 'a' + 10;
else if (c >= 'A')
return c - 'A' + 10;
else
return c - '0';
}
static void
_gtk_css_parser_unescape (GtkCssParser *parser,
GString *str)
{
guint i;
gunichar result = 0;
g_assert (*parser->data == '\\');
parser->data++;
for (i = 0; i < 6; i++)
{
if (!g_ascii_isxdigit (parser->data[i]))
break;
result = (result << 4) + get_xdigit (parser->data[i]);
}
if (i != 0)
{
g_string_append_unichar (str, result);
parser->data += i;
/* NB: gtk_css_parser_new_line() forward data pointer itself */
if (!gtk_css_parser_new_line (parser) &&
*parser->data &&
strchr (WHITESPACE_CHARS, *parser->data))
parser->data++;
return;
}
if (gtk_css_parser_new_line (parser))
return;
g_string_append_c (str, *parser->data);
parser->data++;
return;
}
static gboolean
_gtk_css_parser_read_char (GtkCssParser *parser,
GString * str,
const char * allowed)
{
if (*parser->data == 0)
return FALSE;
if (strchr (allowed, *parser->data))
{
g_string_append_c (str, *parser->data);
parser->data++;
return TRUE;
}
if (*parser->data >= 127)
{
gsize len = g_utf8_skip[(guint) *(guchar *) parser->data];
g_string_append_len (str, parser->data, len);
parser->data += len;
return TRUE;
}
if (*parser->data == '\\')
{
_gtk_css_parser_unescape (parser, str);
return TRUE;
}
return FALSE;
}
static char *
_gtk_css_parser_get_ident (GtkCssParser *parser)
{
char *result;
gsize len;
len = parser->ident_str->len;
result = g_new (char, len + 1);
memcpy (result, parser->ident_str->str, len + 1);
g_string_set_size (parser->ident_str, 0);
return result;
}
char *
_gtk_css_parser_try_name (GtkCssParser *parser,
gboolean skip_whitespace)
{
GString *name;
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);
if (parser->ident_str == NULL)
parser->ident_str = g_string_new (NULL);
name = parser->ident_str;
while (_gtk_css_parser_read_char (parser, name, NMCHAR))
;
if (skip_whitespace)
_gtk_css_parser_skip_whitespace (parser);
return _gtk_css_parser_get_ident (parser);
}
char *
_gtk_css_parser_try_ident (GtkCssParser *parser,
gboolean skip_whitespace)
{
const char *start;
GString *ident;
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);
start = parser->data;
if (parser->ident_str == NULL)
parser->ident_str = g_string_new (NULL);
ident = parser->ident_str;
if (*parser->data == '-')
{
g_string_append_c (ident, '-');
parser->data++;
}
if (!_gtk_css_parser_read_char (parser, ident, NMSTART))
{
parser->data = start;
g_string_set_size (ident, 0);
return NULL;
}
while (_gtk_css_parser_read_char (parser, ident, NMCHAR))
;
if (skip_whitespace)
_gtk_css_parser_skip_whitespace (parser);
return _gtk_css_parser_get_ident (parser);
}
gboolean
_gtk_css_parser_is_string (GtkCssParser *parser)
{
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
return *parser->data == '"' || *parser->data == '\'';
}
char *
_gtk_css_parser_read_string (GtkCssParser *parser)
{
GString *str;
char quote;
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);
quote = *parser->data;
if (quote != '"' && quote != '\'')
{
_gtk_css_parser_error (parser, "Expected a string.");
return NULL;
}
parser->data++;
if (parser->ident_str == NULL)
parser->ident_str = g_string_new (NULL);
str = parser->ident_str;
g_assert (str->len == 0);
while (TRUE)
{
gsize len = strcspn (parser->data, "\\'\"\n\r\f");
g_string_append_len (str, parser->data, len);
parser->data += len;
switch (*parser->data)
{
case '\\':
_gtk_css_parser_unescape (parser, str);
break;
case '"':
case '\'':
if (*parser->data == quote)
{
parser->data++;
_gtk_css_parser_skip_whitespace (parser);
return _gtk_css_parser_get_ident (parser);
}
g_string_append_c (str, *parser->data);
parser->data++;
break;
case '\0':
/* FIXME: position */
_gtk_css_parser_error (parser, "Missing end quote in string.");
g_string_set_size (str, 0);
return NULL;
default:
_gtk_css_parser_error (parser,
"Invalid character in string. Must be escaped.");
g_string_set_size (str, 0);
return NULL;
}
}
g_assert_not_reached ();
return NULL;
}
gboolean
_gtk_css_parser_try_int (GtkCssParser *parser,
int *value)
{
gint64 result;
char *end;
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
g_return_val_if_fail (value != NULL, FALSE);
/* strtoll parses a plus, but we are not allowed to */
if (*parser->data == '+')
return FALSE;
errno = 0;
result = g_ascii_strtoll (parser->data, &end, 10);
if (errno)
return FALSE;
if (result > G_MAXINT || result < G_MININT)
return FALSE;
if (parser->data == end)
return FALSE;
parser->data = end;
*value = result;
_gtk_css_parser_skip_whitespace (parser);
return TRUE;
}
gboolean
_gtk_css_parser_try_double (GtkCssParser *parser,
gdouble *value)
{
gdouble result;
char *end;
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
g_return_val_if_fail (value != NULL, FALSE);
errno = 0;
result = g_ascii_strtod (parser->data, &end);
if (errno)
return FALSE;
if (parser->data == end)
return FALSE;
parser->data = end;
*value = result;
_gtk_css_parser_skip_whitespace (parser);
return TRUE;
}
gboolean
_gtk_css_parser_has_number (GtkCssParser *parser)
{
char c;
if (parser->data[0] == '-' || parser->data[0] == '+')
c = parser->data[1];
else
c = parser->data[0];
/* ahem */
return g_ascii_isdigit (c) || c == '.';
}
GtkCssValue *
gtk_css_dimension_value_parse (GtkCssParser *parser,
GtkCssNumberParseFlags flags)
{
static const struct {
const char *name;
GtkCssUnit unit;
GtkCssNumberParseFlags required_flags;
} units[] = {
{ "px", GTK_CSS_PX, GTK_CSS_PARSE_LENGTH },
{ "pt", GTK_CSS_PT, GTK_CSS_PARSE_LENGTH },
{ "em", GTK_CSS_EM, GTK_CSS_PARSE_LENGTH },
{ "ex", GTK_CSS_EX, GTK_CSS_PARSE_LENGTH },
{ "rem", GTK_CSS_REM, GTK_CSS_PARSE_LENGTH },
{ "pc", GTK_CSS_PC, GTK_CSS_PARSE_LENGTH },
{ "in", GTK_CSS_IN, GTK_CSS_PARSE_LENGTH },
{ "cm", GTK_CSS_CM, GTK_CSS_PARSE_LENGTH },
{ "mm", GTK_CSS_MM, GTK_CSS_PARSE_LENGTH },
{ "rad", GTK_CSS_RAD, GTK_CSS_PARSE_ANGLE },
{ "deg", GTK_CSS_DEG, GTK_CSS_PARSE_ANGLE },
{ "grad", GTK_CSS_GRAD, GTK_CSS_PARSE_ANGLE },
{ "turn", GTK_CSS_TURN, GTK_CSS_PARSE_ANGLE },
{ "s", GTK_CSS_S, GTK_CSS_PARSE_TIME },
{ "ms", GTK_CSS_MS, GTK_CSS_PARSE_TIME }
};
char *end, *unit_name;
double value;
GtkCssUnit unit;
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);
errno = 0;
value = g_ascii_strtod (parser->data, &end);
if (errno)
{
_gtk_css_parser_error (parser, "not a number: %s", g_strerror (errno));
return NULL;
}
if (parser->data == end)
{
_gtk_css_parser_error (parser, "not a number");
return NULL;
}
parser->data = end;
if (flags & GTK_CSS_POSITIVE_ONLY &&
value < 0)
{
_gtk_css_parser_error (parser, "negative values are not allowed.");
return NULL;
}
unit_name = _gtk_css_parser_try_ident (parser, FALSE);
if (unit_name)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (units); i++)
{
if (flags & units[i].required_flags &&
g_ascii_strcasecmp (unit_name, units[i].name) == 0)
break;
}
if (i >= G_N_ELEMENTS (units))
{
_gtk_css_parser_error (parser, "'%s' is not a valid unit.", unit_name);
g_free (unit_name);
return NULL;
}
unit = units[i].unit;
g_free (unit_name);
}
else
{
if ((flags & GTK_CSS_PARSE_PERCENT) &&
_gtk_css_parser_try (parser, "%", FALSE))
{
unit = GTK_CSS_PERCENT;
}
else if (value == 0.0)
{
if (flags & GTK_CSS_PARSE_NUMBER)
unit = GTK_CSS_NUMBER;
else if (flags & GTK_CSS_PARSE_LENGTH)
unit = GTK_CSS_PX;
else if (flags & GTK_CSS_PARSE_ANGLE)
unit = GTK_CSS_DEG;
else if (flags & GTK_CSS_PARSE_TIME)
unit = GTK_CSS_S;
else
unit = GTK_CSS_PERCENT;
}
else if (flags & GTK_CSS_PARSE_NUMBER)
{
unit = GTK_CSS_NUMBER;
}
else
{
_gtk_css_parser_error (parser, "Unit is missing.");
return NULL;
}
}
_gtk_css_parser_skip_whitespace (parser);
return gtk_css_dimension_value_new (value, unit);
}
gboolean
_gtk_css_parser_try_hash_color (GtkCssParser *parser,
GdkRGBA *rgba)
{
if (parser->data[0] == '#' &&
g_ascii_isxdigit (parser->data[1]) &&
g_ascii_isxdigit (parser->data[2]) &&
g_ascii_isxdigit (parser->data[3]))
{
if (g_ascii_isxdigit (parser->data[4]))
{
if (g_ascii_isxdigit (parser->data[5]) &&
g_ascii_isxdigit (parser->data[6]))
{
rgba->red = ((get_xdigit (parser->data[1]) << 4) + get_xdigit (parser->data[2])) / 255.0;
rgba->green = ((get_xdigit (parser->data[3]) << 4) + get_xdigit (parser->data[4])) / 255.0;
rgba->blue = ((get_xdigit (parser->data[5]) << 4) + get_xdigit (parser->data[6])) / 255.0;
if (g_ascii_isxdigit (parser->data[7]) &&
g_ascii_isxdigit (parser->data[8]))
{
rgba->alpha = ((get_xdigit (parser->data[7]) << 4) + get_xdigit (parser->data[8])) / 255.0;
parser->data += 9;
}
else
{
rgba->alpha = 1.0;
parser->data += 7;
}
}
else
{
rgba->red = get_xdigit (parser->data[1]) / 15.0;
rgba->green = get_xdigit (parser->data[2]) / 15.0;
rgba->blue = get_xdigit (parser->data[3]) / 15.0;
rgba->alpha = get_xdigit (parser->data[4]) / 15.0;
parser->data += 5;
}
}
else
{
rgba->red = get_xdigit (parser->data[1]) / 15.0;
rgba->green = get_xdigit (parser->data[2]) / 15.0;
rgba->blue = get_xdigit (parser->data[3]) / 15.0;
rgba->alpha = 1.0;
parser->data += 4;
}
_gtk_css_parser_skip_whitespace (parser);
return TRUE;
}
return FALSE;
}
GFile *
_gtk_css_parser_read_url (GtkCssParser *parser)
{
gchar *path;
char *scheme;
GFile *file;
if (_gtk_css_parser_try (parser, "url", FALSE))
{
if (!_gtk_css_parser_try (parser, "(", TRUE))
{
_gtk_css_parser_error (parser, "Expected '(' after 'url'");
return NULL;
}
path = _gtk_css_parser_read_string (parser);
if (path == NULL)
return NULL;
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
_gtk_css_parser_error (parser, "No closing ')' found for 'url'");
g_free (path);
return NULL;
}
scheme = g_uri_parse_scheme (path);
if (scheme != NULL)
{
file = g_file_new_for_uri (path);
g_free (path);
g_free (scheme);
return file;
}
}
else
{
path = _gtk_css_parser_try_name (parser, TRUE);
if (path == NULL)
{
_gtk_css_parser_error (parser, "Not a valid url");
return NULL;
}
}
file = _gtk_css_parser_get_file_for_path (parser, path);
g_free (path);
return file;
}
static void
gtk_css_parser_resync_internal (GtkCssParser *parser,
gboolean sync_at_semicolon,
gboolean read_sync_token,
char terminator)
{
gsize len;
do {
len = strcspn (parser->data, "\\\"'/()[]{};" NEWLINE_CHARS);
parser->data += len;
if (gtk_css_parser_new_line (parser))
continue;
if (_gtk_css_parser_is_string (parser))
{
/* Hrm, this emits errors, and i suspect it shouldn't... */
char *free_me = _gtk_css_parser_read_string (parser);
g_free (free_me);
continue;
}
if (gtk_css_parser_skip_comment (parser))
continue;
switch (*parser->data)
{
case '\\':
{
GString *ignore = g_string_new (NULL);
_gtk_css_parser_unescape (parser, ignore);
g_string_free (ignore, TRUE);
}
break;
case ';':
if (sync_at_semicolon && !read_sync_token)
return;
parser->data++;
if (sync_at_semicolon)
{
_gtk_css_parser_skip_whitespace (parser);
return;
}
break;
case '(':
parser->data++;
_gtk_css_parser_resync (parser, FALSE, ')');
if (*parser->data)
parser->data++;
break;
case '[':
parser->data++;
_gtk_css_parser_resync (parser, FALSE, ']');
if (*parser->data)
parser->data++;
break;
case '{':
parser->data++;
_gtk_css_parser_resync (parser, FALSE, '}');
if (*parser->data)
parser->data++;
if (sync_at_semicolon || !terminator)
{
_gtk_css_parser_skip_whitespace (parser);
return;
}
break;
case '}':
case ')':
case ']':
if (terminator == *parser->data)
{
_gtk_css_parser_skip_whitespace (parser);
return;
}
parser->data++;
continue;
case '\0':
break;
case '/':
default:
parser->data++;
break;
}
} while (*parser->data);
}
void
_gtk_css_parser_resync (GtkCssParser *parser,
gboolean sync_at_semicolon,
char terminator)
{
g_return_if_fail (GTK_IS_CSS_PARSER (parser));
gtk_css_parser_resync_internal (parser, sync_at_semicolon, TRUE, terminator);
}
void
_gtk_css_print_string (GString *str,
const char *string)
+4 -62
View File
@@ -20,70 +20,12 @@
#include <gtk/gtkcssprovider.h>
#include <gtk/css/gtkcss.h>
#include "gtk/css/gtkcsstokenizerprivate.h"
#include "gtk/css/gtkcssparserprivate.h"
G_BEGIN_DECLS
typedef struct _GtkCssParser GtkCssParser;
typedef void (* GtkCssParserErrorFunc) (GtkCssParser *parser,
const GError *error,
gpointer user_data);
GtkCssParser * _gtk_css_parser_new (const char *data,
GFile *file,
GtkCssParserErrorFunc error_func,
gpointer user_data);
void _gtk_css_parser_free (GtkCssParser *parser);
void _gtk_css_parser_take_error (GtkCssParser *parser,
GError *error);
void _gtk_css_parser_error (GtkCssParser *parser,
const char *format,
...) G_GNUC_PRINTF (2, 3);
guint _gtk_css_parser_get_line (GtkCssParser *parser);
guint _gtk_css_parser_get_position (GtkCssParser *parser);
GFile * _gtk_css_parser_get_file (GtkCssParser *parser);
GFile * _gtk_css_parser_get_file_for_path (GtkCssParser *parser,
const char *path);
gboolean _gtk_css_parser_is_eof (GtkCssParser *parser);
gboolean _gtk_css_parser_begins_with (GtkCssParser *parser,
char c);
gboolean _gtk_css_parser_has_prefix (GtkCssParser *parser,
const char *prefix);
gboolean _gtk_css_parser_is_string (GtkCssParser *parser);
/* IMPORTANT:
* _try_foo() functions do not modify the data pointer if they fail, nor do they
* signal an error. _read_foo() will modify the data pointer and position it at
* the first token that is broken and emit an error about the failure.
* So only call _read_foo() when you know that you are reading a foo. _try_foo()
* however is fine to call if you dont know yet if the token is a foo or a bar,
* you can _try_bar() if try_foo() failed.
*/
gboolean _gtk_css_parser_try (GtkCssParser *parser,
const char *string,
gboolean skip_whitespace);
char * _gtk_css_parser_try_ident (GtkCssParser *parser,
gboolean skip_whitespace);
char * _gtk_css_parser_try_name (GtkCssParser *parser,
gboolean skip_whitespace);
gboolean _gtk_css_parser_try_int (GtkCssParser *parser,
int *value);
gboolean _gtk_css_parser_try_double (GtkCssParser *parser,
gdouble *value);
gboolean _gtk_css_parser_try_hash_color (GtkCssParser *parser,
GdkRGBA *rgba);
gboolean _gtk_css_parser_has_number (GtkCssParser *parser);
char * _gtk_css_parser_read_string (GtkCssParser *parser);
GFile * _gtk_css_parser_read_url (GtkCssParser *parser);
void _gtk_css_parser_skip_whitespace (GtkCssParser *parser);
void _gtk_css_parser_resync (GtkCssParser *parser,
gboolean sync_at_semicolon,
char terminator);
/* XXX: Find better place to put it? */
void _gtk_css_print_string (GString *str,
const char *string);
+48 -42
View File
@@ -179,42 +179,34 @@ position_value_parse (GtkCssParser *parser, gboolean try)
const char *name;
guint percentage;
gboolean horizontal;
gboolean vertical;
gboolean swap;
} names[] = {
{ "left", 0, TRUE, FALSE },
{ "right", 100, TRUE, FALSE },
{ "center", 50, TRUE, TRUE },
{ "top", 0, FALSE, TRUE },
{ "bottom", 100, FALSE, TRUE },
{ NULL , 0, TRUE, FALSE }, /* used for numbers */
{ NULL , 50, TRUE, TRUE } /* used for no value */
{ "top", 0, FALSE, FALSE },
{ "bottom", 100, FALSE, FALSE },
};
GtkCssValue *x, *y;
GtkCssValue **missing;
guint first, second;
GtkCssValue *x = NULL, *y = NULL;
gboolean swap = FALSE;
guint i;
for (first = 0; names[first].name != NULL; first++)
for (i = 0; i < G_N_ELEMENTS (names); i++)
{
if (_gtk_css_parser_try (parser, names[first].name, TRUE))
if (gtk_css_parser_try_ident (parser, names[i].name))
{
if (names[first].horizontal)
{
x = _gtk_css_number_value_new (names[first].percentage, GTK_CSS_PERCENT);
missing = &y;
}
if (names[i].horizontal)
x = _gtk_css_number_value_new (names[i].percentage, GTK_CSS_PERCENT);
else
{
y = _gtk_css_number_value_new (names[first].percentage, GTK_CSS_PERCENT);
missing = &x;
}
y = _gtk_css_number_value_new (names[i].percentage, GTK_CSS_PERCENT);
swap = names[i].swap;
break;
}
}
if (names[first].name == NULL)
if (i == G_N_ELEMENTS (names))
{
if (gtk_css_number_value_can_parse (parser))
{
missing = &y;
x = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_PERCENT
| GTK_CSS_PARSE_LENGTH);
@@ -225,28 +217,52 @@ position_value_parse (GtkCssParser *parser, gboolean try)
else
{
if (!try)
_gtk_css_parser_error (parser, "Unrecognized position value");
gtk_css_parser_error_syntax (parser, "Unrecognized position value");
return NULL;
}
}
for (second = 0; names[second].name != NULL; second++)
for (i = 0; i < G_N_ELEMENTS (names); i++)
{
if (_gtk_css_parser_try (parser, names[second].name, TRUE))
if (!swap && !names[i].swap)
{
*missing = _gtk_css_number_value_new (names[second].percentage, GTK_CSS_PERCENT);
if (names[i].horizontal && x != NULL)
continue;
if (!names[i].horizontal && y != NULL)
continue;
}
if (gtk_css_parser_try_ident (parser, names[i].name))
{
if (x)
{
if (names[i].horizontal && !names[i].swap)
{
y = x;
x = _gtk_css_number_value_new (names[i].percentage, GTK_CSS_PERCENT);
}
else
{
y = _gtk_css_number_value_new (names[i].percentage, GTK_CSS_PERCENT);
}
}
else
{
g_assert (names[i].horizontal || names[i].swap);
x = _gtk_css_number_value_new (names[i].percentage, GTK_CSS_PERCENT);
}
break;
}
}
if (names[second].name == NULL)
if (i == G_N_ELEMENTS (names))
{
if (gtk_css_number_value_can_parse (parser))
{
if (missing != &y)
if (y != NULL)
{
if (!try)
_gtk_css_parser_error (parser, "Invalid combination of values");
gtk_css_parser_error_syntax (parser, "Invalid combination of values");
_gtk_css_value_unref (y);
return NULL;
}
@@ -261,20 +277,10 @@ position_value_parse (GtkCssParser *parser, gboolean try)
}
else
{
second++;
*missing = _gtk_css_number_value_new (50, GTK_CSS_PERCENT);
}
}
else
{
if ((names[first].horizontal && !names[second].vertical) ||
(!names[first].horizontal && !names[second].horizontal))
{
if (!try)
_gtk_css_parser_error (parser, "Invalid combination of values");
_gtk_css_value_unref (x);
_gtk_css_value_unref (y);
return NULL;
if (y)
x = _gtk_css_number_value_new (50, GTK_CSS_PERCENT);
else
y = _gtk_css_number_value_new (50, GTK_CSS_PERCENT);
}
}
+177 -411
View File
@@ -17,12 +17,6 @@
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <cairo-gobject.h>
#include "gtkcssproviderprivate.h"
#include "gtkbitmaskprivate.h"
@@ -30,7 +24,6 @@
#include "gtkcsscolorvalueprivate.h"
#include "gtkcsskeyframesprivate.h"
#include "gtkcssparserprivate.h"
#include "gtkcsssectionprivate.h"
#include "gtkcssselectorprivate.h"
#include "gtkcssshorthandpropertyprivate.h"
#include "gtksettingsprivate.h"
@@ -45,6 +38,12 @@
#include "gtkintl.h"
#include "gtkversion.h"
#include <string.h>
#include <stdlib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <cairo-gobject.h>
/**
* SECTION:gtkcssprovider
* @Short_description: CSS-like styling for widgets
@@ -103,7 +102,6 @@ struct _GtkCssScanner
{
GtkCssProvider *provider;
GtkCssParser *parser;
GtkCssSection *section;
GtkCssScanner *parent;
GSList *state;
};
@@ -140,13 +138,7 @@ static void
gtk_css_provider_load_internal (GtkCssProvider *css_provider,
GtkCssScanner *scanner,
GFile *file,
const char *data);
GQuark
gtk_css_provider_error_quark (void)
{
return g_quark_from_static_string ("gtk-css-provider-error-quark");
}
GBytes *bytes);
G_DEFINE_TYPE_EXTENDED (GtkCssProvider, gtk_css_provider, G_TYPE_OBJECT, 0,
G_ADD_PRIVATE (GtkCssProvider)
@@ -169,7 +161,7 @@ gtk_css_provider_parsing_error (GtkCssProvider *provider,
0,
TRUE))
{
char *s = _gtk_css_section_to_string (section);
char *s = gtk_css_section_to_string (section);
g_warning ("Theme parsing error: %s: %s",
s,
@@ -315,10 +307,8 @@ gtk_css_ruleset_add (GtkCssRuleset *ruleset,
static void
gtk_css_scanner_destroy (GtkCssScanner *scanner)
{
if (scanner->section)
gtk_css_section_unref (scanner->section);
g_object_unref (scanner->provider);
_gtk_css_parser_free (scanner->parser);
gtk_css_parser_unref (scanner->parser);
g_slice_free (GtkCssScanner, scanner);
}
@@ -332,31 +322,29 @@ gtk_css_style_provider_emit_error (GtkStyleProvider *provider,
}
static void
gtk_css_provider_emit_error (GtkCssProvider *provider,
GtkCssScanner *scanner,
const GError *error)
{
gtk_css_style_provider_emit_error (GTK_STYLE_PROVIDER (provider),
scanner ? scanner->section : NULL,
error);
}
static void
gtk_css_scanner_parser_error (GtkCssParser *parser,
const GError *error,
gpointer user_data)
gtk_css_scanner_parser_error (GtkCssParser *parser,
const GtkCssLocation *start,
const GtkCssLocation *end,
const GError *error,
gpointer user_data)
{
GtkCssScanner *scanner = user_data;
GtkCssSection *section;
gtk_css_provider_emit_error (scanner->provider, scanner, error);
section = gtk_css_section_new (gtk_css_parser_get_file (parser),
start,
end);
gtk_css_style_provider_emit_error (GTK_STYLE_PROVIDER (scanner->provider), section, error);
gtk_css_section_unref (section);
}
static GtkCssScanner *
gtk_css_scanner_new (GtkCssProvider *provider,
GtkCssScanner *parent,
GtkCssSection *section,
GFile *file,
const gchar *text)
GBytes *bytes)
{
GtkCssScanner *scanner;
@@ -365,13 +353,13 @@ gtk_css_scanner_new (GtkCssProvider *provider,
g_object_ref (provider);
scanner->provider = provider;
scanner->parent = parent;
if (section)
scanner->section = gtk_css_section_ref (section);
scanner->parser = _gtk_css_parser_new (text,
file,
gtk_css_scanner_parser_error,
scanner);
scanner->parser = gtk_css_parser_new_for_bytes (bytes,
file,
NULL,
gtk_css_scanner_parser_error,
scanner,
NULL);
return scanner;
}
@@ -382,7 +370,7 @@ gtk_css_scanner_would_recurse (GtkCssScanner *scanner,
{
while (scanner)
{
GFile *parser_file = _gtk_css_parser_get_file (scanner->parser);
GFile *parser_file = gtk_css_parser_get_file (scanner->parser);
if (parser_file && g_file_equal (parser_file, file))
return TRUE;
@@ -392,39 +380,6 @@ gtk_css_scanner_would_recurse (GtkCssScanner *scanner,
return FALSE;
}
static void
gtk_css_scanner_push_section (GtkCssScanner *scanner,
GtkCssSectionType section_type)
{
GtkCssSection *section;
section = _gtk_css_section_new (scanner->section,
section_type,
scanner->parser);
if (scanner->section)
gtk_css_section_unref (scanner->section);
scanner->section = section;
}
static void
gtk_css_scanner_pop_section (GtkCssScanner *scanner,
GtkCssSectionType check_type)
{
GtkCssSection *parent;
g_assert (gtk_css_section_get_section_type (scanner->section) == check_type);
parent = gtk_css_section_get_parent (scanner->section);
if (parent)
gtk_css_section_ref (parent);
_gtk_css_section_end (scanner->section);
gtk_css_section_unref (scanner->section);
scanner->section = parent;
}
static void
gtk_css_provider_init (GtkCssProvider *css_provider)
{
@@ -664,67 +619,6 @@ gtk_css_provider_new (void)
return g_object_new (GTK_TYPE_CSS_PROVIDER, NULL);
}
static void
gtk_css_provider_take_error (GtkCssProvider *provider,
GtkCssScanner *scanner,
GError *error)
{
gtk_css_provider_emit_error (provider, scanner, error);
g_error_free (error);
}
static void
gtk_css_provider_error_literal (GtkCssProvider *provider,
GtkCssScanner *scanner,
GQuark domain,
gint code,
const char *message)
{
gtk_css_provider_take_error (provider,
scanner,
g_error_new_literal (domain, code, message));
}
static void
gtk_css_provider_error (GtkCssProvider *provider,
GtkCssScanner *scanner,
GQuark domain,
gint code,
const char *format,
...) G_GNUC_PRINTF (5, 6);
static void
gtk_css_provider_error (GtkCssProvider *provider,
GtkCssScanner *scanner,
GQuark domain,
gint code,
const char *format,
...)
{
GError *error;
va_list args;
gtk_internal_return_if_fail (GTK_IS_CSS_PROVIDER (provider));
gtk_internal_return_if_fail (scanner != NULL);
va_start (args, format);
error = g_error_new_valist (domain, code, format, args);
va_end (args);
gtk_css_provider_take_error (provider, scanner, error);
}
static void
gtk_css_provider_invalid_token (GtkCssProvider *provider,
GtkCssScanner *scanner,
const char *expected)
{
gtk_css_provider_error (provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
"expected %s", expected);
}
static void
css_provider_commit (GtkCssProvider *css_provider,
GSList *selectors,
@@ -772,7 +666,6 @@ gtk_css_provider_reset (GtkCssProvider *css_provider)
g_array_set_size (priv->rulesets, 0);
_gtk_css_selector_tree_free (priv->tree);
priv->tree = NULL;
}
static gboolean
@@ -780,48 +673,50 @@ parse_import (GtkCssScanner *scanner)
{
GFile *file;
gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_IMPORT);
if (!gtk_css_parser_try_at_keyword (scanner->parser, "import"))
return FALSE;
if (!_gtk_css_parser_try (scanner->parser, "@import", TRUE))
if (gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_STRING))
{
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_IMPORT);
return FALSE;
}
char *url;
if (_gtk_css_parser_is_string (scanner->parser))
{
char *uri;
uri = _gtk_css_parser_read_string (scanner->parser);
file = _gtk_css_parser_get_file_for_path (scanner->parser, uri);
g_free (uri);
url = gtk_css_parser_consume_string (scanner->parser);
if (url)
{
file = gtk_css_parser_resolve_url (scanner->parser, url);
if (file == NULL)
{
gtk_css_parser_error_import (scanner->parser,
"Could not resolve \"%s\" to a valid URL",
url);
}
g_free (url);
}
else
file = NULL;
}
else
{
file = _gtk_css_parser_read_url (scanner->parser);
file = gtk_css_parser_consume_url (scanner->parser);
}
if (file == NULL)
{
_gtk_css_parser_resync (scanner->parser, TRUE, 0);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_IMPORT);
return TRUE;
/* nothing to do */
}
if (!_gtk_css_parser_try (scanner->parser, ";", FALSE))
else if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
{
gtk_css_provider_invalid_token (scanner->provider, scanner, "semicolon");
_gtk_css_parser_resync (scanner->parser, TRUE, 0);
gtk_css_parser_error_syntax (scanner->parser, "Expected ';'");
}
else if (gtk_css_scanner_would_recurse (scanner, file))
{
char *path = g_file_get_path (file);
gtk_css_provider_error (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_IMPORT,
"Loading '%s' would recurse",
path);
gtk_css_parser_error (scanner->parser,
GTK_CSS_PARSER_ERROR_IMPORT,
gtk_css_parser_get_block_location (scanner->parser),
gtk_css_parser_get_end_location (scanner->parser),
"Loading '%s' would recurse",
path);
g_free (path);
}
else
@@ -832,10 +727,7 @@ parse_import (GtkCssScanner *scanner)
NULL);
}
g_object_unref (file);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_IMPORT);
_gtk_css_parser_skip_whitespace (scanner->parser);
g_clear_object (&file);
return TRUE;
}
@@ -847,54 +739,31 @@ parse_color_definition (GtkCssScanner *scanner)
GtkCssValue *color;
char *name;
gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION);
if (!gtk_css_parser_try_at_keyword (scanner->parser, "define-color"))
return FALSE;
if (!_gtk_css_parser_try (scanner->parser, "@define-color", TRUE))
{
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION);
return FALSE;
}
name = _gtk_css_parser_try_name (scanner->parser, TRUE);
name = gtk_css_parser_consume_ident (scanner->parser);
if (name == NULL)
{
gtk_css_provider_error_literal (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
"Not a valid color name");
_gtk_css_parser_resync (scanner->parser, TRUE, 0);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION);
return TRUE;
}
return TRUE;
color = _gtk_css_color_value_parse (scanner->parser);
if (color == NULL)
{
g_free (name);
_gtk_css_parser_resync (scanner->parser, TRUE, 0);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION);
return TRUE;
}
if (!_gtk_css_parser_try (scanner->parser, ";", TRUE))
if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
{
g_free (name);
_gtk_css_value_unref (color);
gtk_css_provider_error_literal (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
"Missing semicolon at end of color definition");
_gtk_css_parser_resync (scanner->parser, TRUE, 0);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION);
gtk_css_parser_error_syntax (scanner->parser,
"Missing semicolon at end of color definition");
return TRUE;
}
g_hash_table_insert (priv->symbolic_colors, name, color);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_COLOR_DEFINITION);
return TRUE;
}
@@ -905,61 +774,27 @@ parse_keyframes (GtkCssScanner *scanner)
GtkCssKeyframes *keyframes;
char *name;
gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_KEYFRAMES);
if (!gtk_css_parser_try_at_keyword (scanner->parser, "keyframes"))
return FALSE;
if (!_gtk_css_parser_try (scanner->parser, "@keyframes", TRUE))
name = gtk_css_parser_consume_ident (scanner->parser);
if (name == NULL)
return FALSE;
if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
{
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_KEYFRAMES);
gtk_css_parser_error_syntax (scanner->parser, "Expected '{' for keyframes");
return FALSE;
}
name = _gtk_css_parser_try_ident (scanner->parser, TRUE);
if (name == NULL)
{
gtk_css_provider_error_literal (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
"Expected name for keyframes");
_gtk_css_parser_resync (scanner->parser, TRUE, 0);
goto exit;
}
if (!_gtk_css_parser_try (scanner->parser, "{", TRUE))
{
gtk_css_provider_error_literal (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
"Expected '{' for keyframes");
_gtk_css_parser_resync (scanner->parser, TRUE, 0);
g_free (name);
goto exit;
}
gtk_css_parser_end_block_prelude (scanner->parser);
keyframes = _gtk_css_keyframes_parse (scanner->parser);
if (keyframes == NULL)
{
_gtk_css_parser_resync (scanner->parser, TRUE, '}');
g_free (name);
goto exit;
}
if (keyframes != NULL)
g_hash_table_insert (priv->keyframes, name, keyframes);
g_hash_table_insert (priv->keyframes, name, keyframes);
if (!_gtk_css_parser_try (scanner->parser, "}", TRUE))
{
gtk_css_provider_error_literal (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
"expected '}' after declarations");
if (!_gtk_css_parser_is_eof (scanner->parser))
_gtk_css_parser_resync (scanner->parser, FALSE, 0);
}
exit:
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_KEYFRAMES);
if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
gtk_css_parser_error_syntax (scanner->parser, "Expected '}' after declarations");
return TRUE;
}
@@ -967,22 +802,16 @@ exit:
static void
parse_at_keyword (GtkCssScanner *scanner)
{
if (parse_import (scanner))
return;
if (parse_color_definition (scanner))
return;
if (parse_keyframes (scanner))
return;
gtk_css_parser_start_semicolon_block (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY);
else
if (!parse_import (scanner) &&
!parse_color_definition (scanner) &&
!parse_keyframes (scanner))
{
gtk_css_provider_error_literal (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
"unknown @ rule");
_gtk_css_parser_resync (scanner->parser, TRUE, 0);
gtk_css_parser_error_syntax (scanner->parser, "Unknown @ rule");
}
gtk_css_parser_end_block (scanner->parser);
}
static GSList *
@@ -990,24 +819,15 @@ parse_selector_list (GtkCssScanner *scanner)
{
GSList *selectors = NULL;
gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_SELECTOR);
do {
GtkCssSelector *select = _gtk_css_selector_parse (scanner->parser);
if (select == NULL)
{
g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
_gtk_css_parser_resync (scanner->parser, FALSE, 0);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_SELECTOR);
return NULL;
}
return NULL;
selectors = g_slist_prepend (selectors, select);
}
while (_gtk_css_parser_try (scanner->parser, ",", TRUE));
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_SELECTOR);
while (gtk_css_parser_try_token (scanner->parser, GTK_CSS_TOKEN_COMMA));
return selectors;
}
@@ -1019,57 +839,64 @@ parse_declaration (GtkCssScanner *scanner,
GtkStyleProperty *property;
char *name;
gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_DECLARATION);
/* advance the location over whitespace */
gtk_css_parser_get_token (scanner->parser);
gtk_css_parser_start_semicolon_block (scanner->parser, GTK_CSS_TOKEN_EOF);
name = _gtk_css_parser_try_ident (scanner->parser, TRUE);
if (name == NULL)
goto check_for_semicolon;
property = _gtk_style_property_lookup (name);
if (!_gtk_css_parser_try (scanner->parser, ":", TRUE))
if (gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
{
gtk_css_provider_invalid_token (scanner->provider, scanner, "':'");
_gtk_css_parser_resync (scanner->parser, TRUE, '}');
g_free (name);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION);
gtk_css_parser_warn_syntax (scanner->parser, "Empty declaration");
gtk_css_parser_end_block (scanner->parser);
return;
}
name = gtk_css_parser_consume_ident (scanner->parser);
if (name == NULL)
{
gtk_css_parser_end_block (scanner->parser);
return;
}
property = _gtk_style_property_lookup (name);
if (property)
{
GtkCssSection *section;
GtkCssValue *value;
g_free (name);
gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_VALUE);
if (!gtk_css_parser_try_token (scanner->parser, GTK_CSS_TOKEN_COLON))
{
gtk_css_parser_error_syntax (scanner->parser, "Expected ':'");
g_free (name);
gtk_css_parser_end_block (scanner->parser);
return;
}
value = _gtk_style_property_parse_value (property,
scanner->parser);
if (value == NULL)
{
_gtk_css_parser_resync (scanner->parser, TRUE, '}');
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION);
gtk_css_parser_end_block (scanner->parser);
return;
}
if (!_gtk_css_parser_begins_with (scanner->parser, ';') &&
!_gtk_css_parser_begins_with (scanner->parser, '}') &&
!_gtk_css_parser_is_eof (scanner->parser))
if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
{
gtk_css_provider_error (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
"Junk at end of value for %s", property->name);
_gtk_css_parser_resync (scanner->parser, TRUE, '}');
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION);
gtk_css_parser_error_syntax (scanner->parser, "Junk at end of value for %s", property->name);
gtk_css_parser_end_block (scanner->parser);
return;
}
if (gtk_keep_css_sections)
{
section = gtk_css_section_new (gtk_css_parser_get_file (scanner->parser),
gtk_css_parser_get_block_location (scanner->parser),
gtk_css_parser_get_end_location (scanner->parser));
}
else
section = NULL;
if (GTK_IS_CSS_SHORTHAND_PROPERTY (property))
{
GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
@@ -1080,14 +907,15 @@ parse_declaration (GtkCssScanner *scanner,
GtkCssStyleProperty *child = _gtk_css_shorthand_property_get_subproperty (shorthand, i);
GtkCssValue *sub = _gtk_css_array_value_get_nth (value, i);
gtk_css_ruleset_add (ruleset, child, _gtk_css_value_ref (sub), scanner->section);
gtk_css_ruleset_add (ruleset, child, _gtk_css_value_ref (sub), section);
}
_gtk_css_value_unref (value);
}
else if (GTK_IS_CSS_STYLE_PROPERTY (property))
{
gtk_css_ruleset_add (ruleset, GTK_CSS_STYLE_PROPERTY (property), value, scanner->section);
gtk_css_ruleset_add (ruleset, GTK_CSS_STYLE_PROPERTY (property), value, section);
}
else
{
@@ -1095,36 +923,23 @@ parse_declaration (GtkCssScanner *scanner,
_gtk_css_value_unref (value);
}
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_VALUE);
g_clear_pointer (&section, gtk_css_section_unref);
}
else
g_free (name);
check_for_semicolon:
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DECLARATION);
if (!_gtk_css_parser_try (scanner->parser, ";", TRUE))
{
if (!_gtk_css_parser_begins_with (scanner->parser, '}') &&
!_gtk_css_parser_is_eof (scanner->parser))
{
gtk_css_provider_error_literal (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
"Expected semicolon");
_gtk_css_parser_resync (scanner->parser, TRUE, '}');
}
gtk_css_parser_error_value (scanner->parser, "No property named \"%s\"", name);
}
g_free (name);
gtk_css_parser_end_block (scanner->parser);
}
static void
parse_declarations (GtkCssScanner *scanner,
GtkCssRuleset *ruleset)
{
while (!_gtk_css_parser_is_eof (scanner->parser) &&
!_gtk_css_parser_begins_with (scanner->parser, '}'))
while (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
{
parse_declaration (scanner, ruleset);
}
@@ -1136,55 +951,37 @@ parse_ruleset (GtkCssScanner *scanner)
GSList *selectors;
GtkCssRuleset ruleset = { 0, };
gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_RULESET);
selectors = parse_selector_list (scanner);
if (selectors == NULL)
{
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_RULESET);
gtk_css_parser_skip_until (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY);
gtk_css_parser_skip (scanner->parser);
return;
}
if (!_gtk_css_parser_try (scanner->parser, "{", TRUE))
if (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY))
{
gtk_css_provider_error_literal (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
"expected '{' after selectors");
_gtk_css_parser_resync (scanner->parser, FALSE, 0);
gtk_css_parser_error_syntax (scanner->parser, "Expected '{' after selectors");
g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_RULESET);
gtk_css_parser_skip_until (scanner->parser, GTK_CSS_TOKEN_OPEN_CURLY);
gtk_css_parser_skip (scanner->parser);
return;
}
gtk_css_parser_start_block (scanner->parser);
parse_declarations (scanner, &ruleset);
if (!_gtk_css_parser_try (scanner->parser, "}", TRUE))
{
gtk_css_provider_error_literal (scanner->provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
"expected '}' after declarations");
if (!_gtk_css_parser_is_eof (scanner->parser))
{
_gtk_css_parser_resync (scanner->parser, FALSE, 0);
g_slist_free_full (selectors, (GDestroyNotify) _gtk_css_selector_free);
gtk_css_ruleset_clear (&ruleset);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_RULESET);
}
}
gtk_css_parser_end_block (scanner->parser);
css_provider_commit (scanner->provider, selectors, &ruleset);
gtk_css_ruleset_clear (&ruleset);
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_RULESET);
}
static void
parse_statement (GtkCssScanner *scanner)
{
if (_gtk_css_parser_begins_with (scanner->parser, '@'))
if (gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_AT_KEYWORD))
parse_at_keyword (scanner);
else
parse_ruleset (scanner);
@@ -1193,20 +990,17 @@ parse_statement (GtkCssScanner *scanner)
static void
parse_stylesheet (GtkCssScanner *scanner)
{
gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_DOCUMENT);
_gtk_css_parser_skip_whitespace (scanner->parser);
while (!_gtk_css_parser_is_eof (scanner->parser))
while (!gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_EOF))
{
if (_gtk_css_parser_try (scanner->parser, "<!--", TRUE) ||
_gtk_css_parser_try (scanner->parser, "-->", TRUE))
continue;
if (gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_CDO) ||
gtk_css_parser_has_token (scanner->parser, GTK_CSS_TOKEN_CDC))
{
gtk_css_parser_consume_token (scanner->parser);
continue;
}
parse_statement (scanner);
}
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DOCUMENT);
}
static int
@@ -1263,77 +1057,55 @@ gtk_css_provider_postprocess (GtkCssProvider *css_provider)
}
static void
gtk_css_provider_load_internal (GtkCssProvider *css_provider,
gtk_css_provider_load_internal (GtkCssProvider *self,
GtkCssScanner *parent,
GFile *file,
const char *text)
GBytes *bytes)
{
GtkCssScanner *scanner;
GBytes *bytes;
if (text == NULL)
if (bytes == NULL)
{
GError *load_error = NULL;
bytes = g_file_load_bytes (file, NULL, NULL, &load_error);
if (bytes)
{
text = g_bytes_get_data (bytes, NULL);
}
else
if (bytes == NULL)
{
if (parent == NULL)
{
scanner = gtk_css_scanner_new (css_provider,
NULL,
NULL,
file,
"");
GtkCssLocation empty = { 0, };
GtkCssSection *section = gtk_css_section_new (file, &empty, &empty);
gtk_css_scanner_push_section (scanner, GTK_CSS_SECTION_DOCUMENT);
gtk_css_style_provider_emit_error (GTK_STYLE_PROVIDER (self), section, load_error);
gtk_css_section_unref (section);
}
else
scanner = parent;
gtk_css_provider_error (css_provider,
scanner,
GTK_CSS_PROVIDER_ERROR,
GTK_CSS_PROVIDER_ERROR_IMPORT,
"Failed to import: %s",
load_error->message);
if (parent == NULL)
{
gtk_css_scanner_pop_section (scanner, GTK_CSS_SECTION_DOCUMENT);
gtk_css_scanner_destroy (scanner);
gtk_css_parser_error (parent->parser,
GTK_CSS_PARSER_ERROR_IMPORT,
gtk_css_parser_get_block_location (parent->parser),
gtk_css_parser_get_end_location (parent->parser),
"Failed to import: %s",
load_error->message);
}
}
}
else
{
bytes = NULL;
}
if (text)
if (bytes)
{
scanner = gtk_css_scanner_new (css_provider,
GtkCssScanner *scanner;
scanner = gtk_css_scanner_new (self,
parent,
parent ? parent->section : NULL,
file,
text);
bytes);
parse_stylesheet (scanner);
gtk_css_scanner_destroy (scanner);
if (parent == NULL)
gtk_css_provider_postprocess (css_provider);
gtk_css_provider_postprocess (self);
}
if (bytes)
g_bytes_unref (bytes);
}
/**
@@ -1352,27 +1124,21 @@ gtk_css_provider_load_from_data (GtkCssProvider *css_provider,
const gchar *data,
gssize length)
{
char *free_data;
GBytes *bytes;
g_return_if_fail (GTK_IS_CSS_PROVIDER (css_provider));
g_return_if_fail (data != NULL);
if (length < 0)
{
length = strlen (data);
free_data = NULL;
}
else
{
free_data = g_strndup (data, length);
data = free_data;
}
length = strlen (data);
bytes = g_bytes_new_static (data, length);
gtk_css_provider_reset (css_provider);
gtk_css_provider_load_internal (css_provider, NULL, NULL, data);
gtk_css_provider_load_internal (css_provider, NULL, NULL, bytes);
g_free (free_data);
g_bytes_unref (bytes);
gtk_style_provider_changed (GTK_STYLE_PROVIDER (css_provider));
}
+1 -32
View File
@@ -19,7 +19,7 @@
#define __GTK_CSS_PROVIDER_H__
#include <gio/gio.h>
#include <gtk/gtkcsssection.h>
#include <gtk/css/gtkcss.h>
G_BEGIN_DECLS
@@ -30,37 +30,6 @@ G_BEGIN_DECLS
#define GTK_IS_CSS_PROVIDER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GTK_TYPE_CSS_PROVIDER))
#define GTK_CSS_PROVIDER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_CSS_PROVIDER, GtkCssProviderClass))
/**
* GTK_CSS_PROVIDER_ERROR:
*
* Domain for #GtkCssProvider errors.
*/
#define GTK_CSS_PROVIDER_ERROR (gtk_css_provider_error_quark ())
/**
* GtkCssProviderError:
* @GTK_CSS_PROVIDER_ERROR_FAILED: Failed.
* @GTK_CSS_PROVIDER_ERROR_SYNTAX: Syntax error.
* @GTK_CSS_PROVIDER_ERROR_IMPORT: Import error.
* @GTK_CSS_PROVIDER_ERROR_NAME: Name error.
* @GTK_CSS_PROVIDER_ERROR_DEPRECATED: Deprecation error.
* @GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE: Unknown value.
*
* Error codes for %GTK_CSS_PROVIDER_ERROR.
*/
typedef enum
{
GTK_CSS_PROVIDER_ERROR_FAILED,
GTK_CSS_PROVIDER_ERROR_SYNTAX,
GTK_CSS_PROVIDER_ERROR_IMPORT,
GTK_CSS_PROVIDER_ERROR_NAME,
GTK_CSS_PROVIDER_ERROR_DEPRECATED,
GTK_CSS_PROVIDER_ERROR_UNKNOWN_VALUE
} GtkCssProviderError;
GDK_AVAILABLE_IN_ALL
GQuark gtk_css_provider_error_quark (void);
typedef struct _GtkCssProvider GtkCssProvider;
typedef struct _GtkCssProviderClass GtkCssProviderClass;
typedef struct _GtkCssProviderPrivate GtkCssProviderPrivate;
+4 -4
View File
@@ -178,7 +178,7 @@ _gtk_css_background_repeat_style_try (GtkCssParser *parser,
for (i = 0; i < G_N_ELEMENTS (background_repeat_values); i++)
{
if (_gtk_css_parser_try (parser, background_repeat_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, background_repeat_values[i].name))
{
*result = i;
return TRUE;
@@ -195,9 +195,9 @@ _gtk_css_background_repeat_value_try_parse (GtkCssParser *parser)
g_return_val_if_fail (parser != NULL, NULL);
if (_gtk_css_parser_try (parser, "repeat-x", TRUE))
if (gtk_css_parser_try_ident (parser, "repeat-x"))
return _gtk_css_background_repeat_value_new (GTK_CSS_REPEAT_STYLE_REPEAT, GTK_CSS_REPEAT_STYLE_NO_REPEAT);
if (_gtk_css_parser_try (parser, "repeat-y", TRUE))
if (gtk_css_parser_try_ident (parser, "repeat-y"))
return _gtk_css_background_repeat_value_new (GTK_CSS_REPEAT_STYLE_NO_REPEAT, GTK_CSS_REPEAT_STYLE_REPEAT);
if (!_gtk_css_background_repeat_style_try (parser, &x))
@@ -272,7 +272,7 @@ _gtk_css_border_repeat_style_try (GtkCssParser *parser,
for (i = 0; i < G_N_ELEMENTS (border_repeat_values); i++)
{
if (_gtk_css_parser_try (parser, border_repeat_values[i].name, TRUE))
if (gtk_css_parser_try_ident (parser, border_repeat_values[i].name))
{
*result = i;
return TRUE;
-321
View File
@@ -1,321 +0,0 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkcsssectionprivate.h"
#include "gtkcssparserprivate.h"
#include "gtkprivate.h"
struct _GtkCssSection
{
gint ref_count;
GtkCssSectionType section_type;
GtkCssSection *parent;
GFile *file;
guint start_line;
guint start_position;
GtkCssParser *parser; /* parser if section isn't finished parsing yet or %NULL */
guint end_line; /* end line if parser is %NULL */
guint end_position; /* end position if parser is %NULL */
};
G_DEFINE_BOXED_TYPE (GtkCssSection, gtk_css_section, gtk_css_section_ref, gtk_css_section_unref)
GtkCssSection *
_gtk_css_section_new (GtkCssSection *parent,
GtkCssSectionType type,
GtkCssParser *parser)
{
GtkCssSection *section;
gtk_internal_return_val_if_fail (parser != NULL, NULL);
section = g_slice_new0 (GtkCssSection);
section->ref_count = 1;
section->section_type = type;
if (parent)
section->parent = gtk_css_section_ref (parent);
section->file = _gtk_css_parser_get_file (parser);
if (section->file)
g_object_ref (section->file);
section->start_line = _gtk_css_parser_get_line (parser);
section->start_position = _gtk_css_parser_get_position (parser);
section->parser = parser;
return section;
}
GtkCssSection *
_gtk_css_section_new_for_file (GtkCssSectionType type,
GFile *file)
{
GtkCssSection *section;
gtk_internal_return_val_if_fail (G_IS_FILE (file), NULL);
section = g_slice_new0 (GtkCssSection);
section->ref_count = 1;
section->section_type = type;
section->file = g_object_ref (file);
return section;
}
void
_gtk_css_section_end (GtkCssSection *section)
{
gtk_internal_return_if_fail (section != NULL);
gtk_internal_return_if_fail (section->parser != NULL);
section->end_line = _gtk_css_parser_get_line (section->parser);
section->end_position = _gtk_css_parser_get_position (section->parser);
section->parser = NULL;
}
/**
* gtk_css_section_ref:
* @section: a #GtkCssSection
*
* Increments the reference count on @section.
*
* Returns: @section itself.
**/
GtkCssSection *
gtk_css_section_ref (GtkCssSection *section)
{
gtk_internal_return_val_if_fail (section != NULL, NULL);
section->ref_count += 1;
return section;
}
/**
* gtk_css_section_unref:
* @section: a #GtkCssSection
*
* Decrements the reference count on @section, freeing the
* structure if the reference count reaches 0.
**/
void
gtk_css_section_unref (GtkCssSection *section)
{
gtk_internal_return_if_fail (section != NULL);
section->ref_count -= 1;
if (section->ref_count > 0)
return;
if (section->parent)
gtk_css_section_unref (section->parent);
if (section->file)
g_object_unref (section->file);
g_slice_free (GtkCssSection, section);
}
/**
* gtk_css_section_get_section_type:
* @section: the section
*
* Gets the type of information that @section describes.
*
* Returns: the type of @section
**/
GtkCssSectionType
gtk_css_section_get_section_type (const GtkCssSection *section)
{
gtk_internal_return_val_if_fail (section != NULL, GTK_CSS_SECTION_DOCUMENT);
return section->section_type;
}
/**
* gtk_css_section_get_parent:
* @section: the section
*
* Gets the parent section for the given @section. The parent section is
* the section that contains this @section. A special case are sections of
* type #GTK_CSS_SECTION_DOCUMENT. Their parent will either be %NULL
* if they are the original CSS document that was loaded by
* gtk_css_provider_load_from_file() or a section of type
* #GTK_CSS_SECTION_IMPORT if it was loaded with an import rule from
* a different file.
*
* Returns: (nullable) (transfer none): the parent section or %NULL if none
**/
GtkCssSection *
gtk_css_section_get_parent (const GtkCssSection *section)
{
gtk_internal_return_val_if_fail (section != NULL, NULL);
return section->parent;
}
/**
* gtk_css_section_get_file:
* @section: the section
*
* Gets the file that @section was parsed from. If no such file exists,
* for example because the CSS was loaded via
* @gtk_css_provider_load_from_data(), then %NULL is returned.
*
* Returns: (transfer none): the #GFile that @section was parsed from
* or %NULL if @section was parsed from other data
**/
GFile *
gtk_css_section_get_file (const GtkCssSection *section)
{
gtk_internal_return_val_if_fail (section != NULL, NULL);
return section->file;
}
/**
* gtk_css_section_get_start_line:
* @section: the section
*
* Returns the line in the CSS document where this section starts.
* The line number is 0-indexed, so the first line of the document
* will return 0.
*
* Returns: the line number
**/
guint
gtk_css_section_get_start_line (const GtkCssSection *section)
{
gtk_internal_return_val_if_fail (section != NULL, 0);
return section->start_line;
}
/**
* gtk_css_section_get_start_position:
* @section: the section
*
* Returns the offset in bytes from the start of the current line
* returned via gtk_css_section_get_start_line().
*
* Returns: the offset in bytes from the start of the line.
**/
guint
gtk_css_section_get_start_position (const GtkCssSection *section)
{
gtk_internal_return_val_if_fail (section != NULL, 0);
return section->start_position;
}
/**
* gtk_css_section_get_end_line:
* @section: the section
*
* Returns the line in the CSS document where this section end.
* The line number is 0-indexed, so the first line of the document
* will return 0.
* This value may change in future invocations of this function if
* @section is not yet parsed completely. This will for example
* happen in the GtkCssProvider::parsing-error signal.
* The end position and line may be identical to the start
* position and line for sections which failed to parse anything
* successfully.
*
* Returns: the line number
**/
guint
gtk_css_section_get_end_line (const GtkCssSection *section)
{
gtk_internal_return_val_if_fail (section != NULL, 0);
if (section->parser)
return _gtk_css_parser_get_line (section->parser);
else
return section->end_line;
}
/**
* gtk_css_section_get_end_position:
* @section: the section
*
* Returns the offset in bytes from the start of the current line
* returned via gtk_css_section_get_end_line().
* This value may change in future invocations of this function if
* @section is not yet parsed completely. This will for example
* happen in the GtkCssProvider::parsing-error signal.
* The end position and line may be identical to the start
* position and line for sections which failed to parse anything
* successfully.
*
* Returns: the offset in bytes from the start of the line.
**/
guint
gtk_css_section_get_end_position (const GtkCssSection *section)
{
gtk_internal_return_val_if_fail (section != NULL, 0);
if (section->parser)
return _gtk_css_parser_get_position (section->parser);
else
return section->end_position;
}
void
_gtk_css_section_print (const GtkCssSection *section,
GString *string)
{
if (section->file)
{
GFileInfo *info;
info = g_file_query_info (section->file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, 0, NULL, NULL);
if (info)
{
g_string_append (string, g_file_info_get_display_name (info));
g_object_unref (info);
}
else
{
g_string_append (string, "<broken file>");
}
}
else
{
g_string_append (string, "<data>");
}
g_string_append_printf (string, ":%u:%u",
gtk_css_section_get_end_line (section) + 1,
gtk_css_section_get_end_position (section));
}
char *
_gtk_css_section_to_string (const GtkCssSection *section)
{
GString *string;
gtk_internal_return_val_if_fail (section != NULL, NULL);
string = g_string_new (NULL);
_gtk_css_section_print (section, string);
return g_string_free (string, FALSE);
}
-41
View File
@@ -1,41 +0,0 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_CSS_SECTION_PRIVATE_H__
#define __GTK_CSS_SECTION_PRIVATE_H__
#include "gtkcsssection.h"
#include "gtkcssparserprivate.h"
G_BEGIN_DECLS
GtkCssSection * _gtk_css_section_new (GtkCssSection *parent,
GtkCssSectionType type,
GtkCssParser *parser);
GtkCssSection * _gtk_css_section_new_for_file (GtkCssSectionType type,
GFile *file);
void _gtk_css_section_end (GtkCssSection *section);
void _gtk_css_section_print (const GtkCssSection *section,
GString *string);
char * _gtk_css_section_to_string (const GtkCssSection *section);
G_END_DECLS
#endif /* __GTK_CSS_SECTION_PRIVATE_H__ */
+626 -302
View File
@@ -25,6 +25,7 @@
#include "gtkcssprovider.h"
#include "gtkstylecontextprivate.h"
#include <errno.h>
#if defined(_MSC_VER) && _MSC_VER >= 1500
# include <intrin.h>
#endif
@@ -922,337 +923,621 @@ gtk_css_selector_new (const GtkCssSelectorClass *class,
}
static GtkCssSelector *
parse_selector_class (GtkCssParser *parser,
GtkCssSelector *selector,
gboolean negate)
{
char *name;
name = _gtk_css_parser_try_name (parser, FALSE);
if (name == NULL)
{
_gtk_css_parser_error (parser, "Expected a valid name for class");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_CLASS
: &GTK_CSS_SELECTOR_CLASS,
selector);
selector->style_class.style_class = g_quark_from_string (name);
g_free (name);
return selector;
}
static GtkCssSelector *
parse_selector_id (GtkCssParser *parser,
GtkCssSelector *selector,
gboolean negate)
{
char *name;
name = _gtk_css_parser_try_name (parser, FALSE);
if (name == NULL)
{
_gtk_css_parser_error (parser, "Expected a valid name for id");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_ID
: &GTK_CSS_SELECTOR_ID,
selector);
selector->id.name = g_intern_string (name);
g_free (name);
return selector;
}
static GtkCssSelector *
parse_selector_pseudo_class_nth_child (GtkCssParser *parser,
gtk_css_selector_parse_selector_class (GtkCssParser *parser,
GtkCssSelector *selector,
PositionType type,
gboolean negate)
{
int a, b;
const GtkCssToken *token;
if (!_gtk_css_parser_try (parser, "(", TRUE))
gtk_css_parser_consume_token (parser);
for (token = gtk_css_parser_peek_token (parser);
gtk_css_token_is (token, GTK_CSS_TOKEN_COMMENT);
token = gtk_css_parser_peek_token (parser))
{
_gtk_css_parser_error (parser, "Missing opening bracket for pseudo-class");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
gtk_css_parser_consume_token (parser);
}
if (_gtk_css_parser_try (parser, "even", TRUE))
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
a = 2;
b = 0;
}
else if (_gtk_css_parser_try (parser, "odd", TRUE))
{
a = 2;
b = 1;
}
else if (type == POSITION_FORWARD &&
_gtk_css_parser_try (parser, "first", TRUE))
{
a = 0;
b = 1;
}
else if (type == POSITION_FORWARD &&
_gtk_css_parser_try (parser, "last", TRUE))
{
a = 0;
b = 1;
type = POSITION_BACKWARD;
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_CLASS
: &GTK_CSS_SELECTOR_CLASS,
selector);
selector->style_class.style_class = g_quark_from_string (token->string.string);
gtk_css_parser_consume_token (parser);
return selector;
}
else
{
int multiplier;
gtk_css_parser_error_syntax (parser, "No class name after '.' in selector");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
}
if (_gtk_css_parser_try (parser, "+", TRUE))
multiplier = 1;
else if (_gtk_css_parser_try (parser, "-", TRUE))
multiplier = -1;
else
multiplier = 1;
static gboolean
string_has_number (const char *string,
const char *prefix,
int *number)
{
gsize len = strlen (prefix);
char *end;
if (_gtk_css_parser_try_int (parser, &a))
if (g_ascii_strncasecmp (string, prefix, len) != 0)
return FALSE;
errno = 0;
*number = strtoul (string + len, &end, 10);
if (*end != '\0' || errno != 0)
return FALSE;
return TRUE;
}
static gboolean
parse_plus_b (GtkCssParser *parser,
gboolean negate,
gint *b)
{
const GtkCssToken *token;
gboolean has_seen_sign;
token = gtk_css_parser_get_token (parser);
if (negate)
{
has_seen_sign = TRUE;
}
else
{
if (gtk_css_token_is_delim (token, '+'))
{
if (a < 0)
gtk_css_parser_consume_token (parser);
has_seen_sign = TRUE;
}
else if (gtk_css_token_is_delim (token, '-'))
{
gtk_css_parser_consume_token (parser);
negate = TRUE;
has_seen_sign = TRUE;
}
else
{
has_seen_sign = FALSE;
}
}
token = gtk_css_parser_get_token (parser);
if (!has_seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER))
{
*b = token->number.number;
gtk_css_parser_consume_token (parser);
return TRUE;
}
else if (has_seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER))
{
*b = token->number.number;
if (negate)
*b = - *b;
gtk_css_parser_consume_token (parser);
return TRUE;
}
else if (!has_seen_sign)
{
*b = 0;
return TRUE;
}
gtk_css_parser_error_syntax (parser, "Not a valid an+b type");
return FALSE;
}
static gboolean
parse_n_plus_b (GtkCssParser *parser,
gint before,
gint *a,
gint *b)
{
const GtkCssToken *token;
token = gtk_css_parser_get_token (parser);
if (gtk_css_token_is_ident (token, "n"))
{
*a = before;
gtk_css_parser_consume_token (parser);
return parse_plus_b (parser, FALSE, b);
}
else if (gtk_css_token_is_ident (token, "n-"))
{
*a = before;
gtk_css_parser_consume_token (parser);
return parse_plus_b (parser, TRUE, b);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) &&
string_has_number (token->string.string, "n-", b))
{
*a = before;
*b = -*b;
gtk_css_parser_consume_token (parser);
return TRUE;
}
else
{
*b = before;
*a = 0;
return TRUE;
}
gtk_css_parser_error_syntax (parser, "Not a valid an+b type");
return FALSE;
}
static gboolean
parse_a_n_plus_b (GtkCssParser *parser,
gint seen_sign,
gint *a,
gint *b)
{
const GtkCssToken *token;
token = gtk_css_parser_get_token (parser);
if (!seen_sign && gtk_css_token_is_ident (token, "even"))
{
*a = 2;
*b = 0;
gtk_css_parser_consume_token (parser);
return TRUE;
}
else if (!seen_sign && gtk_css_token_is_ident (token, "odd"))
{
*a = 2;
*b = 1;
gtk_css_parser_consume_token (parser);
return TRUE;
}
else if (!seen_sign && gtk_css_token_is_delim (token, '+'))
{
gtk_css_parser_consume_token (parser);
return parse_a_n_plus_b (parser, 1, a, b);
}
else if (!seen_sign && gtk_css_token_is_delim (token, '-'))
{
gtk_css_parser_consume_token (parser);
return parse_a_n_plus_b (parser, -1, a, b);
}
else if ((!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER)) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER))
{
int x = token->number.number * (seen_sign ? seen_sign : 1);
gtk_css_parser_consume_token (parser);
return parse_n_plus_b (parser, x , a, b);
}
else if (((!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION)) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION)) &&
g_ascii_strcasecmp (token->dimension.dimension, "n") == 0)
{
*a = token->dimension.value * (seen_sign ? seen_sign : 1);
gtk_css_parser_consume_token (parser);
return parse_plus_b (parser, FALSE, b);
}
else if (((!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION)) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION)) &&
g_ascii_strcasecmp (token->dimension.dimension, "n-") == 0)
{
*a = token->dimension.value * (seen_sign ? seen_sign : 1);
gtk_css_parser_consume_token (parser);
return parse_plus_b (parser, TRUE, b);
}
else if (((!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER_DIMENSION)) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER_DIMENSION)) &&
string_has_number (token->dimension.dimension, "n-", b))
{
*a = token->dimension.value * (seen_sign ? seen_sign : 1);
*b = -*b;
gtk_css_parser_consume_token (parser);
return TRUE;
}
else if (!seen_sign && gtk_css_token_is_ident (token, "-n"))
{
*a = -1;
gtk_css_parser_consume_token (parser);
return parse_plus_b (parser, FALSE, b);
}
else if (!seen_sign && gtk_css_token_is_ident (token, "-n-"))
{
*a = -1;
gtk_css_parser_consume_token (parser);
return parse_plus_b (parser, TRUE, b);
}
else if (!seen_sign &&
gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) &&
string_has_number (token->string.string, "-n-", b))
{
*a = -1;
*b = -*b;
gtk_css_parser_consume_token (parser);
return TRUE;
}
else if (gtk_css_token_is_ident (token, "n") ||
gtk_css_token_is_ident (token, "n-"))
{
return parse_n_plus_b (parser, seen_sign ? seen_sign : 1, a, b);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) &&
string_has_number (token->string.string, "n-", b))
{
*a = seen_sign ? seen_sign : 1;
*b = -*b;
gtk_css_parser_consume_token (parser);
return TRUE;
}
else if (!seen_sign && gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) &&
string_has_number (token->string.string, "-n-", b))
{
*a = -1;
*b = -*b;
gtk_css_parser_consume_token (parser);
return TRUE;
}
gtk_css_parser_error_syntax (parser, "Not a valid an+b type");
return FALSE;
}
static guint
parse_a_n_plus_b_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
gint *ab = data;
if (!parse_a_n_plus_b (parser, FALSE, &ab[0], &ab[1]))
return 0;
return 1;
}
static guint
parse_dir_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
GtkStateFlags *flag = data;
if (gtk_css_parser_try_ident (parser, "ltr"))
{
*flag = GTK_STATE_FLAG_DIR_LTR;
return 1;
}
else if (gtk_css_parser_try_ident (parser, "rtl"))
{
*flag = GTK_STATE_FLAG_DIR_RTL;
return 1;
}
else
{
gtk_css_parser_error_value (parser, "Expected \"ltr\" or \"rtl\"");
return 0;
}
}
static guint
parse_identifier_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
const char *ident = data;
if (!gtk_css_parser_try_ident (parser, ident))
{
gtk_css_parser_error_value (parser, "Expected \"%s\"", ident);
return 0;
}
return 1;
}
static GtkCssSelector *
gtk_css_selector_parse_selector_pseudo_class (GtkCssParser *parser,
GtkCssSelector *selector,
gboolean negate)
{
GtkCssLocation start_location;
const GtkCssToken *token;
start_location = *gtk_css_parser_get_start_location (parser);
gtk_css_parser_consume_token (parser);
for (token = gtk_css_parser_peek_token (parser);
gtk_css_token_is (token, GTK_CSS_TOKEN_COMMENT);
token = gtk_css_parser_peek_token (parser))
{
gtk_css_parser_consume_token (parser);
}
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
static const struct {
const char *name;
GtkStateFlags state_flag;
PositionType position_type;
int position_a;
int position_b;
} pseudo_classes[] = {
{ "first-child", 0, POSITION_FORWARD, 0, 1 },
{ "last-child", 0, POSITION_BACKWARD, 0, 1 },
{ "only-child", 0, POSITION_ONLY, 0, 0 },
{ "active", GTK_STATE_FLAG_ACTIVE, },
{ "hover", GTK_STATE_FLAG_PRELIGHT, },
{ "selected", GTK_STATE_FLAG_SELECTED, },
{ "disabled", GTK_STATE_FLAG_INSENSITIVE, },
{ "indeterminate", GTK_STATE_FLAG_INCONSISTENT, },
{ "focus", GTK_STATE_FLAG_FOCUSED, },
{ "backdrop", GTK_STATE_FLAG_BACKDROP, },
{ "link", GTK_STATE_FLAG_LINK, },
{ "visited", GTK_STATE_FLAG_VISITED, },
{ "checked", GTK_STATE_FLAG_CHECKED, },
};
guint i;
for (i = 0; i < G_N_ELEMENTS (pseudo_classes); i++)
{
if (g_ascii_strcasecmp (pseudo_classes[i].name, token->string.string) == 0)
{
if (pseudo_classes[i].state_flag)
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
selector->state.state = pseudo_classes[i].state_flag;
}
else
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
: &GTK_CSS_SELECTOR_PSEUDOCLASS_POSITION,
selector);
selector->position.type = pseudo_classes[i].position_type;
selector->position.a = pseudo_classes[i].position_a;
selector->position.b = pseudo_classes[i].position_b;
}
gtk_css_parser_consume_token (parser);
return selector;
}
}
gtk_css_parser_error (parser,
GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE,
&start_location,
gtk_css_parser_get_end_location (parser),
"Unknown name of pseudo-class");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_FUNCTION))
{
if (gtk_css_token_is_function (token, "nth-child"))
{
gint ab[2];
if (!gtk_css_parser_consume_function (parser, 1, 1, parse_a_n_plus_b_arg, ab))
{
_gtk_css_parser_error (parser, "Expected an integer");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
a *= multiplier;
}
else if (_gtk_css_parser_has_prefix (parser, "n"))
{
a = multiplier;
}
else
{
_gtk_css_parser_error (parser, "Expected an integer");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
if (_gtk_css_parser_try (parser, "n", TRUE))
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
: &GTK_CSS_SELECTOR_PSEUDOCLASS_POSITION,
selector);
selector->position.type = POSITION_FORWARD;
selector->position.a = ab[0];
selector->position.b = ab[1];
}
else if (gtk_css_token_is_function (token, "nth-last-child"))
{
if (_gtk_css_parser_try (parser, "+", TRUE))
multiplier = 1;
else if (_gtk_css_parser_try (parser, "-", TRUE))
multiplier = -1;
else
multiplier = 1;
gint ab[2];
if (_gtk_css_parser_try_int (parser, &b))
if (!gtk_css_parser_consume_function (parser, 1, 1, parse_a_n_plus_b_arg, ab))
{
if (b < 0)
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
: &GTK_CSS_SELECTOR_PSEUDOCLASS_POSITION,
selector);
selector->position.type = POSITION_BACKWARD;
selector->position.a = ab[0];
selector->position.b = ab[1];
}
else if (gtk_css_token_is_function (token, "not"))
{
if (negate)
{
gtk_css_parser_error_syntax (parser, "Nesting of :not() not allowed");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
else
{
gtk_css_parser_start_block (parser);
token = gtk_css_parser_get_token (parser);
if (gtk_css_token_is_delim (token, '*'))
{
_gtk_css_parser_error (parser, "Expected an integer");
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NOT_ANY, selector);
gtk_css_parser_consume_token (parser);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NOT_NAME, selector);
selector->name.name = g_intern_string (token->string.string);
gtk_css_parser_consume_token (parser);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NOT_ID, selector);
selector->id.name = g_intern_string (token->string.string);
gtk_css_parser_consume_token (parser);
}
else if (gtk_css_token_is_delim (token, '.'))
{
selector = gtk_css_selector_parse_selector_class (parser, selector, TRUE);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_COLON))
{
selector = gtk_css_selector_parse_selector_pseudo_class (parser, selector, TRUE);
}
else
{
gtk_css_parser_error_syntax (parser, "Invalid contents of :not() selector");
if (selector)
_gtk_css_selector_free (selector);
selector = NULL;
return NULL;
}
}
else
b = 0;
b *= multiplier;
token = gtk_css_parser_get_token (parser);
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
{
gtk_css_parser_error_syntax (parser, "Invalid contents of :not() selector");
if (selector)
_gtk_css_selector_free (selector);
selector = NULL;
return NULL;
}
gtk_css_parser_end_block (parser);
}
}
else if (gtk_css_token_is_function (token, "dir"))
{
GtkStateFlags flag;
if (!gtk_css_parser_consume_function (parser, 1, 1, parse_dir_arg, &flag))
{
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
selector->state.state = flag;
}
else if (gtk_css_token_is_function (token, "drop"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, parse_identifier_arg, (gpointer) "active"))
{
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
selector->state.state = GTK_STATE_FLAG_DROP_ACTIVE;
}
else if (gtk_css_token_is_function (token, "focus"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, parse_identifier_arg, (gpointer) "visible"))
{
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
selector->state.state = GTK_STATE_FLAG_FOCUS_VISIBLE;
}
else
{
b = a;
a = 0;
}
}
if (!_gtk_css_parser_try (parser, ")", FALSE))
{
_gtk_css_parser_error (parser, "Missing closing bracket for pseudo-class");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
: &GTK_CSS_SELECTOR_PSEUDOCLASS_POSITION,
selector);
selector->position.type = type;
selector->position.a = a;
selector->position.b = b;
return selector;
}
static GtkCssSelector *
parse_selector_pseudo_class (GtkCssParser *parser,
GtkCssSelector *selector,
gboolean negate)
{
static const struct {
const char *name;
GtkStateFlags state_flag;
PositionType position_type;
int position_a;
int position_b;
} pseudo_classes[] = {
{ "first-child", 0, POSITION_FORWARD, 0, 1 },
{ "last-child", 0, POSITION_BACKWARD, 0, 1 },
{ "only-child", 0, POSITION_ONLY, 0, 0 },
{ "active", GTK_STATE_FLAG_ACTIVE, },
{ "hover", GTK_STATE_FLAG_PRELIGHT, },
{ "selected", GTK_STATE_FLAG_SELECTED, },
{ "disabled", GTK_STATE_FLAG_INSENSITIVE, },
{ "indeterminate", GTK_STATE_FLAG_INCONSISTENT, },
{ "focus(visible)", GTK_STATE_FLAG_FOCUS_VISIBLE, },
{ "focus", GTK_STATE_FLAG_FOCUSED, },
{ "backdrop", GTK_STATE_FLAG_BACKDROP, },
{ "dir(ltr)", GTK_STATE_FLAG_DIR_LTR, },
{ "dir(rtl)", GTK_STATE_FLAG_DIR_RTL, },
{ "link", GTK_STATE_FLAG_LINK, },
{ "visited", GTK_STATE_FLAG_VISITED, },
{ "checked", GTK_STATE_FLAG_CHECKED, },
{ "drop(active)", GTK_STATE_FLAG_DROP_ACTIVE, }
};
guint i;
if (_gtk_css_parser_try (parser, "nth-child", FALSE))
return parse_selector_pseudo_class_nth_child (parser, selector, POSITION_FORWARD, negate);
else if (_gtk_css_parser_try (parser, "nth-last-child", FALSE))
return parse_selector_pseudo_class_nth_child (parser, selector, POSITION_BACKWARD, negate);
for (i = 0; i < G_N_ELEMENTS (pseudo_classes); i++)
{
if (_gtk_css_parser_try (parser, pseudo_classes[i].name, FALSE))
{
if (pseudo_classes[i].state_flag)
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_STATE
: &GTK_CSS_SELECTOR_PSEUDOCLASS_STATE,
selector);
selector->state.state = pseudo_classes[i].state_flag;
}
else
{
selector = gtk_css_selector_new (negate ? &GTK_CSS_SELECTOR_NOT_PSEUDOCLASS_POSITION
: &GTK_CSS_SELECTOR_PSEUDOCLASS_POSITION,
selector);
selector->position.type = pseudo_classes[i].position_type;
selector->position.a = pseudo_classes[i].position_a;
selector->position.b = pseudo_classes[i].position_b;
}
return selector;
}
}
_gtk_css_parser_error (parser, "Invalid name of pseudo-class");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
static GtkCssSelector *
parse_selector_negation (GtkCssParser *parser,
GtkCssSelector *selector)
{
char *name;
name = _gtk_css_parser_try_ident (parser, FALSE);
if (name)
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NOT_NAME,
selector);
selector->name.name = g_intern_string (name);
g_free (name);
}
else if (_gtk_css_parser_try (parser, "*", FALSE))
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NOT_ANY, selector);
else if (_gtk_css_parser_try (parser, "#", FALSE))
selector = parse_selector_id (parser, selector, TRUE);
else if (_gtk_css_parser_try (parser, ".", FALSE))
selector = parse_selector_class (parser, selector, TRUE);
else if (_gtk_css_parser_try (parser, ":", FALSE))
selector = parse_selector_pseudo_class (parser, selector, TRUE);
else
{
_gtk_css_parser_error (parser, "Not a valid selector for :not()");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
_gtk_css_parser_skip_whitespace (parser);
if (!_gtk_css_parser_try (parser, ")", FALSE))
{
_gtk_css_parser_error (parser, "Missing closing bracket for :not()");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
return selector;
}
static GtkCssSelector *
parse_simple_selector (GtkCssParser *parser,
GtkCssSelector *selector)
{
gboolean parsed_something = FALSE;
char *name;
name = _gtk_css_parser_try_ident (parser, FALSE);
if (name)
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NAME, selector);
selector->name.name = g_intern_string (name);
g_free (name);
parsed_something = TRUE;
}
else if (_gtk_css_parser_try (parser, "*", FALSE))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_ANY, selector);
parsed_something = TRUE;
}
do {
if (_gtk_css_parser_try (parser, "#", FALSE))
selector = parse_selector_id (parser, selector, FALSE);
else if (_gtk_css_parser_try (parser, ".", FALSE))
selector = parse_selector_class (parser, selector, FALSE);
else if (_gtk_css_parser_try (parser, ":not(", TRUE))
selector = parse_selector_negation (parser, selector);
else if (_gtk_css_parser_try (parser, ":", FALSE))
selector = parse_selector_pseudo_class (parser, selector, FALSE);
else if (!parsed_something)
{
_gtk_css_parser_error (parser, "Expected a valid selector");
gtk_css_parser_error (parser,
GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE,
&start_location,
gtk_css_parser_get_end_location (parser),
"Unknown pseudoclass");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
}
else
{
gtk_css_parser_error (parser,
GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE,
&start_location,
gtk_css_parser_get_end_location (parser),
"Unknown pseudoclass");
if (selector)
_gtk_css_selector_free (selector);
return NULL;
}
return selector;
}
static GtkCssSelector *
gtk_css_selector_parse_simple_selector (GtkCssParser *parser,
GtkCssSelector *selector)
{
gboolean parsed_something = FALSE;
const GtkCssToken *token;
do {
for (token = gtk_css_parser_peek_token (parser);
gtk_css_token_is (token, GTK_CSS_TOKEN_COMMENT);
token = gtk_css_parser_peek_token (parser))
{
gtk_css_parser_consume_token (parser);
}
if (!parsed_something && gtk_css_token_is_delim (token, '*'))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_ANY, selector);
gtk_css_parser_consume_token (parser);
}
else if (!parsed_something && gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NAME, selector);
selector->name.name = g_intern_string (token->string.string);
gtk_css_parser_consume_token (parser);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_ID, selector);
selector->id.name = g_intern_string (token->string.string);
gtk_css_parser_consume_token (parser);
}
else if (gtk_css_token_is_delim (token, '.'))
{
selector = gtk_css_selector_parse_selector_class (parser, selector, FALSE);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_COLON))
{
selector = gtk_css_selector_parse_selector_pseudo_class (parser, selector, FALSE);
}
else
break;
{
if (!parsed_something)
{
gtk_css_parser_error_syntax (parser, "Expected a valid selector");
if (selector)
_gtk_css_selector_free (selector);
selector = NULL;
}
break;
}
parsed_something = TRUE;
}
while (selector && !_gtk_css_parser_is_eof (parser));
_gtk_css_parser_skip_whitespace (parser);
while (TRUE);
return selector;
}
@@ -1261,20 +1546,59 @@ GtkCssSelector *
_gtk_css_selector_parse (GtkCssParser *parser)
{
GtkCssSelector *selector = NULL;
const GtkCssToken *token;
while ((selector = parse_simple_selector (parser, selector)) &&
!_gtk_css_parser_is_eof (parser) &&
!_gtk_css_parser_begins_with (parser, ',') &&
!_gtk_css_parser_begins_with (parser, '{'))
while (TRUE)
{
if (_gtk_css_parser_try (parser, "+", TRUE))
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_ADJACENT, selector);
else if (_gtk_css_parser_try (parser, "~", TRUE))
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_SIBLING, selector);
else if (_gtk_css_parser_try (parser, ">", TRUE))
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_CHILD, selector);
gboolean seen_whitespace = FALSE;
/* skip all whitespace and comments */
gtk_css_parser_get_token (parser);
selector = gtk_css_selector_parse_simple_selector (parser, selector);
if (selector == NULL)
return NULL;
for (token = gtk_css_parser_peek_token (parser);
gtk_css_token_is (token, GTK_CSS_TOKEN_COMMENT) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_WHITESPACE);
token = gtk_css_parser_peek_token (parser))
{
seen_whitespace |= gtk_css_token_is (token, GTK_CSS_TOKEN_WHITESPACE);
gtk_css_parser_consume_token (parser);
}
if (gtk_css_token_is_delim (token, '+'))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_ADJACENT, selector);
gtk_css_parser_consume_token (parser);
}
else if (gtk_css_token_is_delim (token, '~'))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_SIBLING, selector);
gtk_css_parser_consume_token (parser);
}
else if (gtk_css_token_is_delim (token, '>'))
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_CHILD, selector);
gtk_css_parser_consume_token (parser);
}
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_COMMA) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_OPEN_CURLY))
{
break;
}
else if (seen_whitespace)
{
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_DESCENDANT, selector);
}
else
selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_DESCENDANT, selector);
{
gtk_css_parser_error_syntax (parser, "Expected a valid selector");
_gtk_css_selector_free (selector);
return NULL;
}
}
return selector;
+2 -2
View File
@@ -240,7 +240,7 @@ _gtk_css_shadows_value_parse (GtkCssParser *parser,
GtkCssValue *value, *result;
GPtrArray *values;
if (_gtk_css_parser_try (parser, "none", TRUE))
if (gtk_css_parser_try_ident (parser, "none"))
return _gtk_css_shadows_value_new_none ();
values = g_ptr_array_new ();
@@ -256,7 +256,7 @@ _gtk_css_shadows_value_parse (GtkCssParser *parser,
}
g_ptr_array_add (values, value);
} while (_gtk_css_parser_try (parser, ",", TRUE));
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
result = gtk_css_shadows_value_new ((GtkCssValue **) values->pdata, values->len);
g_ptr_array_free (values, TRUE);
+105 -82
View File
@@ -201,109 +201,132 @@ _gtk_css_shadow_value_new_for_transition (GtkCssValue *target)
_gtk_css_rgba_value_new_from_rgba (&transparent));
}
enum {
HOFFSET,
VOFFSET,
RADIUS,
SPREAD,
N_VALUES
};
static gboolean
value_is_done_parsing (GtkCssParser *parser)
has_inset (GtkCssParser *parser,
gpointer option_data,
gpointer box_shadow_mode)
{
return _gtk_css_parser_is_eof (parser) ||
_gtk_css_parser_begins_with (parser, ',') ||
_gtk_css_parser_begins_with (parser, ';') ||
_gtk_css_parser_begins_with (parser, '}');
return box_shadow_mode && gtk_css_parser_has_ident (parser, "inset");
}
static gboolean
parse_inset (GtkCssParser *parser,
gpointer option_data,
gpointer box_shadow_mode)
{
gboolean *inset = option_data;
if (!gtk_css_parser_try_ident (parser, "inset"))
{
g_assert_not_reached ();
return FALSE;
}
*inset = TRUE;
return TRUE;
}
static gboolean
parse_lengths (GtkCssParser *parser,
gpointer option_data,
gpointer box_shadow_mode)
{
GtkCssValue **values = option_data;
values[HOFFSET] = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_LENGTH);
if (values[HOFFSET] == NULL)
return FALSE;
values[VOFFSET] = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_LENGTH);
if (values[VOFFSET] == NULL)
return FALSE;
if (gtk_css_number_value_can_parse (parser))
{
values[RADIUS] = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_LENGTH
| GTK_CSS_POSITIVE_ONLY);
if (values[RADIUS] == NULL)
return FALSE;
}
else
values[RADIUS] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
if (box_shadow_mode && gtk_css_number_value_can_parse (parser))
{
values[SPREAD] = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_LENGTH);
if (values[SPREAD] == NULL)
return FALSE;
}
else
values[SPREAD] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
return TRUE;
}
static gboolean
parse_color (GtkCssParser *parser,
gpointer option_data,
gpointer box_shadow_mode)
{
GtkCssValue **color = option_data;
*color = _gtk_css_color_value_parse (parser);
if (*color == NULL)
return FALSE;
return TRUE;
}
GtkCssValue *
_gtk_css_shadow_value_parse (GtkCssParser *parser,
gboolean box_shadow_mode)
{
enum {
HOFFSET,
VOFFSET,
RADIUS,
SPREAD,
COLOR,
N_VALUES
};
GtkCssValue *values[N_VALUES] = { NULL, };
gboolean inset;
GtkCssValue *color = NULL;
gboolean inset = FALSE;
GtkCssParseOption options[] =
{
{ (void *) gtk_css_number_value_can_parse, parse_lengths, values },
{ has_inset, parse_inset, &inset },
{ (void *) gtk_css_color_value_can_parse, parse_color, &color },
};
guint i;
if (box_shadow_mode)
inset = _gtk_css_parser_try (parser, "inset", TRUE);
else
inset = FALSE;
if (!gtk_css_parser_consume_any (parser, options, G_N_ELEMENTS (options), GUINT_TO_POINTER (box_shadow_mode)))
goto fail;
do
{
if (values[HOFFSET] == NULL &&
gtk_css_number_value_can_parse (parser))
{
values[HOFFSET] = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_LENGTH);
if (values[HOFFSET] == NULL)
goto fail;
if (values[0] == NULL)
{
gtk_css_parser_error_syntax (parser, "Expected shadow value to contain a length");
goto fail;
}
values[VOFFSET] = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_LENGTH);
if (values[VOFFSET] == NULL)
goto fail;
if (gtk_css_number_value_can_parse (parser))
{
values[RADIUS] = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_LENGTH
| GTK_CSS_POSITIVE_ONLY);
if (values[RADIUS] == NULL)
goto fail;
}
else
values[RADIUS] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
if (box_shadow_mode && gtk_css_number_value_can_parse (parser))
{
values[SPREAD] = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_LENGTH);
if (values[SPREAD] == NULL)
goto fail;
}
else
values[SPREAD] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
}
else if (!inset && box_shadow_mode && _gtk_css_parser_try (parser, "inset", TRUE))
{
if (values[HOFFSET] == NULL)
goto fail;
inset = TRUE;
break;
}
else if (values[COLOR] == NULL)
{
values[COLOR] = _gtk_css_color_value_parse (parser);
if (values[COLOR] == NULL)
goto fail;
}
else
{
/* We parsed everything and there's still stuff left?
* Pretend we didn't notice and let the normal code produce
* a 'junk at end of value' error */
goto fail;
}
}
while (values[HOFFSET] == NULL || !value_is_done_parsing (parser));
if (values[COLOR] == NULL)
values[COLOR] = _gtk_css_color_value_new_current_color ();
if (color == NULL)
color = _gtk_css_color_value_new_current_color ();
return gtk_css_shadow_value_new (values[HOFFSET], values[VOFFSET],
values[RADIUS], values[SPREAD],
inset, values[COLOR]);
inset, color);
fail:
for (i = 0; i < N_VALUES; i++)
{
if (values[i])
_gtk_css_value_unref (values[i]);
g_clear_pointer (&values[i], gtk_css_value_unref);
}
g_clear_pointer (&color, gtk_css_value_unref);
return NULL;
}
+3 -3
View File
@@ -84,7 +84,7 @@ gtk_css_shorthand_property_parse_value (GtkStyleProperty *property,
data = g_new0 (GtkCssValue *, shorthand->subproperties->len);
if (_gtk_css_parser_try (parser, "initial", TRUE))
if (gtk_css_parser_try_ident (parser, "initial"))
{
/* the initial value can be explicitly specified with the
* initial keyword which all properties accept.
@@ -94,7 +94,7 @@ gtk_css_shorthand_property_parse_value (GtkStyleProperty *property,
data[i] = _gtk_css_initial_value_new ();
}
}
else if (_gtk_css_parser_try (parser, "inherit", TRUE))
else if (gtk_css_parser_try_ident (parser, "inherit"))
{
/* All properties accept the inherit value which
* explicitly specifies that the value will be determined
@@ -107,7 +107,7 @@ gtk_css_shorthand_property_parse_value (GtkStyleProperty *property,
data[i] = _gtk_css_inherit_value_new ();
}
}
else if (_gtk_css_parser_try (parser, "unset", TRUE))
else if (gtk_css_parser_try_ident (parser, "unset"))
{
/* If the cascaded value of a property is the unset keyword,
* then if it is an inherited property, this is treated as
+123 -85
View File
@@ -50,10 +50,10 @@
static gboolean
value_is_done_parsing (GtkCssParser *parser)
{
return _gtk_css_parser_is_eof (parser) ||
_gtk_css_parser_begins_with (parser, ',') ||
_gtk_css_parser_begins_with (parser, ';') ||
_gtk_css_parser_begins_with (parser, '}');
return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_COMMA) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SEMICOLON) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_CLOSE_CURLY);
}
static gboolean
@@ -76,7 +76,7 @@ parse_four_numbers (GtkCssShorthandProperty *shorthand,
if (i == 0)
{
_gtk_css_parser_error (parser, "Expected a length");
gtk_css_parser_error_syntax (parser, "Expected a length");
return FALSE;
}
@@ -145,7 +145,7 @@ parse_border_radius (GtkCssShorthandProperty *shorthand,
if (i == 0)
{
_gtk_css_parser_error (parser, "Expected a number");
gtk_css_parser_error_syntax (parser, "Expected a number");
goto fail;
}
@@ -155,7 +155,7 @@ parse_border_radius (GtkCssShorthandProperty *shorthand,
for (; i < 4; i++)
x[i] = _gtk_css_value_ref (x[(i - 1) >> 1]);
if (_gtk_css_parser_try (parser, "/", TRUE))
if (gtk_css_parser_try_delim (parser, '/'))
{
for (i = 0; i < 4; i++)
{
@@ -171,7 +171,7 @@ parse_border_radius (GtkCssShorthandProperty *shorthand,
if (i == 0)
{
_gtk_css_parser_error (parser, "Expected a number");
gtk_css_parser_error_syntax (parser, "Expected a number");
goto fail;
}
@@ -243,7 +243,7 @@ parse_border_style (GtkCssShorthandProperty *shorthand,
if (i == 0)
{
_gtk_css_parser_error (parser, "Expected a border style");
gtk_css_parser_error_syntax (parser, "Expected a border style");
return FALSE;
}
@@ -261,12 +261,12 @@ parse_border_image (GtkCssShorthandProperty *shorthand,
do
{
if (values[0] == NULL &&
(_gtk_css_parser_has_prefix (parser, "none") ||
(gtk_css_parser_has_ident (parser, "none") ||
_gtk_css_image_can_parse (parser)))
{
GtkCssImage *image;
if (_gtk_css_parser_try (parser, "none", TRUE))
if (gtk_css_parser_try_ident (parser, "none"))
image = NULL;
else
{
@@ -293,7 +293,7 @@ parse_border_image (GtkCssShorthandProperty *shorthand,
if (values[1] == NULL)
return FALSE;
if (_gtk_css_parser_try (parser, "/", TRUE))
if (gtk_css_parser_try_delim (parser, '/'))
{
values[2] = _gtk_css_border_value_parse (parser,
GTK_CSS_PARSE_PERCENT
@@ -418,9 +418,9 @@ parse_border (GtkCssShorthandProperty *shorthand,
static GtkCssValue *
_gtk_css_font_variant_value_try_parse (GtkCssParser *parser)
{
if (_gtk_css_parser_try (parser, "normal", TRUE))
if (gtk_css_parser_try_ident (parser, "normal"))
return _gtk_css_ident_value_new ("normal");
else if (_gtk_css_parser_try (parser, "small-caps", TRUE))
else if (gtk_css_parser_try_ident (parser, "small-caps"))
return _gtk_css_ident_value_new ("small-caps");
return NULL;
}
@@ -450,7 +450,33 @@ parse_font (GtkCssShorthandProperty *shorthand,
if (values[3] == NULL)
{
values[3] = _gtk_css_font_weight_value_try_parse (parser);
values[3] = gtk_css_font_weight_value_try_parse (parser);
if (values[3] == NULL && gtk_css_number_value_can_parse (parser))
{
/* This needs to check for font-size, too */
GtkCssValue *num = _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_NUMBER |
GTK_CSS_PARSE_LENGTH |
GTK_CSS_PARSE_PERCENT |
GTK_CSS_POSITIVE_ONLY);
if (num == NULL)
return FALSE;
if (gtk_css_number_value_get_dimension (num) != GTK_CSS_DIMENSION_NUMBER)
{
values[5] = num;
goto have_font_size;
}
values[3] = num;
if (_gtk_css_number_value_get (values[3], 100) < 1 ||
_gtk_css_number_value_get (values[3], 100) > 1000)
{
gtk_css_parser_error_value (parser, "Font weight values must be between 1 and 1000");
g_clear_pointer (&values[3], gtk_css_value_unref);
return FALSE;
}
}
parsed_one = parsed_one || values[3] != NULL;
}
@@ -463,10 +489,15 @@ parse_font (GtkCssShorthandProperty *shorthand,
while (parsed_one && !value_is_done_parsing (parser));
values[5] = gtk_css_font_size_value_parse (parser);
if (values[5] == NULL)
return FALSE;
have_font_size:
values[0] = gtk_css_font_family_value_parse (parser);
if (values[0] == NULL)
return FALSE;
return values[0] != NULL && values[5] != NULL;
return TRUE;
}
static gboolean
@@ -480,12 +511,12 @@ parse_one_background (GtkCssShorthandProperty *shorthand,
{
/* the image part */
if (values[0] == NULL &&
(_gtk_css_parser_has_prefix (parser, "none") ||
(gtk_css_parser_has_ident (parser, "none") ||
_gtk_css_image_can_parse (parser)))
{
GtkCssImage *image;
if (_gtk_css_parser_try (parser, "none", TRUE))
if (gtk_css_parser_try_ident (parser, "none"))
image = NULL;
else
{
@@ -502,7 +533,7 @@ parse_one_background (GtkCssShorthandProperty *shorthand,
values[1] = value;
value = NULL;
if (_gtk_css_parser_try (parser, "/", TRUE) &&
if (gtk_css_parser_try_delim (parser, '/') &&
(value = _gtk_css_bg_size_value_parse (parser)))
{
values[2] = value;
@@ -595,7 +626,7 @@ parse_background (GtkCssShorthandProperty *shorthand,
g_ptr_array_add (arrays[i], step_values[i]);
step_values[i] = NULL;
}
} while (_gtk_css_parser_try (parser, ",", TRUE));
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
for (i = 0; i < 6; i++)
{
@@ -608,57 +639,64 @@ parse_background (GtkCssShorthandProperty *shorthand,
return TRUE;
}
static gboolean
has_transition_property (GtkCssParser *parser,
gpointer option_data,
gpointer user_data)
{
return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_IDENT);
}
static gboolean
parse_transition_property (GtkCssParser *parser,
gpointer option_data,
gpointer user_data)
{
GtkCssValue **value = option_data;
*value = _gtk_css_ident_value_try_parse (parser);
g_assert (*value);
return TRUE;
}
static gboolean
parse_transition_time (GtkCssParser *parser,
gpointer option_data,
gpointer user_data)
{
GtkCssValue **value = option_data;
*value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_TIME);
return *value != NULL;
}
static gboolean
parse_transition_timing_function (GtkCssParser *parser,
gpointer option_data,
gpointer user_data)
{
GtkCssValue **value = option_data;
*value = _gtk_css_ease_value_parse (parser);
return *value != NULL;
}
static gboolean
parse_one_transition (GtkCssShorthandProperty *shorthand,
GtkCssValue **values,
GtkCssParser *parser)
{
do
{
/* the image part */
if (values[2] == NULL &&
gtk_css_number_value_can_parse (parser) && !_gtk_css_parser_begins_with (parser, '-'))
{
GtkCssValue *number = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_TIME);
const GtkCssParseOption options[] = {
{ (void *) _gtk_css_ease_value_can_parse, parse_transition_timing_function, &values[3] },
{ (void *) gtk_css_number_value_can_parse, parse_transition_time, &values[1] },
{ (void *) gtk_css_number_value_can_parse, parse_transition_time, &values[2] },
{ (void *) has_transition_property, parse_transition_property, &values[0] },
};
if (number == NULL)
return FALSE;
if (values[1] == NULL)
values[1] = number;
else
values[2] = number;
}
else if (values[3] == NULL &&
_gtk_css_ease_value_can_parse (parser))
{
values[3] = _gtk_css_ease_value_parse (parser);
if (values[3] == NULL)
return FALSE;
}
else if (values[0] == NULL)
{
values[0] = _gtk_css_ident_value_try_parse (parser);
if (values[0] == NULL)
{
_gtk_css_parser_error (parser, "Unknown value for property");
return FALSE;
}
}
else
{
/* We parsed everything and there's still stuff left?
* Pretend we didn't notice and let the normal code produce
* a 'junk at end of value' error
*/
break;
}
}
while (!value_is_done_parsing (parser));
return TRUE;
return gtk_css_parser_consume_any (parser, options, G_N_ELEMENTS (options), NULL);
}
static gboolean
@@ -699,7 +737,7 @@ parse_transition (GtkCssShorthandProperty *shorthand,
g_ptr_array_add (arrays[i], step_values[i]);
step_values[i] = NULL;
}
} while (_gtk_css_parser_try (parser, ",", TRUE));
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
for (i = 0; i < 4; i++)
{
@@ -717,7 +755,7 @@ parse_one_animation (GtkCssShorthandProperty *shorthand,
{
do
{
if (values[1] == NULL && _gtk_css_parser_try (parser, "infinite", TRUE))
if (values[1] == NULL && gtk_css_parser_try_ident (parser, "infinite"))
{
values[1] = _gtk_css_number_value_new (HUGE_VAL, GTK_CSS_NUMBER);
}
@@ -816,7 +854,7 @@ parse_animation (GtkCssShorthandProperty *shorthand,
g_ptr_array_add (arrays[i], step_values[i]);
step_values[i] = NULL;
}
} while (_gtk_css_parser_try (parser, ",", TRUE));
} while (gtk_css_parser_try_token (parser, GTK_CSS_TOKEN_COMMA));
for (i = 0; i < 7; i++)
{
@@ -870,11 +908,11 @@ parse_font_variant (GtkCssShorthandProperty *shorthand,
GtkCssValue **values,
GtkCssParser *parser)
{
if (_gtk_css_parser_try (parser, "normal", TRUE))
if (gtk_css_parser_try_ident (parser, "normal"))
{
/* all initial values */
}
else if (_gtk_css_parser_try (parser, "none", TRUE))
else if (gtk_css_parser_try_ident (parser, "none"))
{
/* all initial values, except for font-variant-ligatures */
values[0] = _gtk_css_font_variant_ligature_value_new (GTK_CSS_FONT_VARIANT_LIGATURE_NONE);
@@ -896,13 +934,13 @@ parse_font_variant (GtkCssShorthandProperty *shorthand,
parsed_ligature = _gtk_css_font_variant_ligature_try_parse_one (parser, ligatures);
if (parsed_ligature == 0 && ligatures != 0)
{
_gtk_css_parser_error (parser, "Invalid combination of ligature values");
gtk_css_parser_error_value (parser, "Invalid combination of ligature values");
return FALSE;
}
if (parsed_ligature == GTK_CSS_FONT_VARIANT_LIGATURE_NORMAL ||
parsed_ligature == GTK_CSS_FONT_VARIANT_LIGATURE_NONE)
{
_gtk_css_parser_error (parser, "Unexpected ligature value");
gtk_css_parser_error_value (parser, "Unexpected ligature value");
return FALSE;
}
if (parsed_ligature != ligatures)
@@ -914,12 +952,12 @@ parse_font_variant (GtkCssShorthandProperty *shorthand,
parsed_numeric = _gtk_css_font_variant_numeric_try_parse_one (parser, numeric);
if (parsed_numeric == 0 && numeric != 0)
{
_gtk_css_parser_error (parser, "Invalid combination of numeric values");
gtk_css_parser_error_value (parser, "Invalid combination of numeric values");
return FALSE;
}
if (parsed_numeric == GTK_CSS_FONT_VARIANT_NUMERIC_NORMAL)
{
_gtk_css_parser_error (parser, "Unexpected numeric value");
gtk_css_parser_error_value (parser, "Unexpected numeric value");
return FALSE;
}
if (parsed_numeric != numeric)
@@ -931,12 +969,12 @@ parse_font_variant (GtkCssShorthandProperty *shorthand,
parsed_east_asian = _gtk_css_font_variant_east_asian_try_parse_one (parser, east_asian);
if (parsed_east_asian == 0 && east_asian != 0)
{
_gtk_css_parser_error (parser, "Invalid combination of east asian values");
gtk_css_parser_error_value (parser, "Invalid combination of east asian values");
return FALSE;
}
if (parsed_east_asian == GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL)
{
_gtk_css_parser_error (parser, "Unexpected east asian value");
gtk_css_parser_error_value (parser, "Unexpected east asian value");
return FALSE;
}
if (parsed_east_asian != east_asian)
@@ -952,7 +990,7 @@ parse_font_variant (GtkCssShorthandProperty *shorthand,
{
if (_gtk_css_font_variant_position_value_get (values[1]) == GTK_CSS_FONT_VARIANT_POSITION_NORMAL)
{
_gtk_css_parser_error (parser, "Unexpected position value");
gtk_css_parser_error_value (parser, "Unexpected position value");
return FALSE;
}
goto found;
@@ -965,7 +1003,7 @@ parse_font_variant (GtkCssShorthandProperty *shorthand,
{
if (_gtk_css_font_variant_caps_value_get (values[2]) == GTK_CSS_FONT_VARIANT_CAPS_NORMAL)
{
_gtk_css_parser_error (parser, "Unexpected caps value");
gtk_css_parser_error_value (parser, "Unexpected caps value");
return FALSE;
}
goto found;
@@ -979,14 +1017,14 @@ parse_font_variant (GtkCssShorthandProperty *shorthand,
{
if (_gtk_css_font_variant_alternate_value_get (values[4]) == GTK_CSS_FONT_VARIANT_ALTERNATE_NORMAL)
{
_gtk_css_parser_error (parser, "Unexpected alternate value");
gtk_css_parser_error_value (parser, "Unexpected alternate value");
return FALSE;
}
goto found;
}
}
_gtk_css_parser_error (parser, "Unknown value for property");
gtk_css_parser_error_value (parser, "Unknown value for property");
return FALSE;
found:
@@ -1000,7 +1038,7 @@ found:
values[0] = _gtk_css_font_variant_ligature_value_new (ligatures);
if (values[0] == NULL)
{
_gtk_css_parser_error (parser, "Invalid combination of ligature values");
gtk_css_parser_error_value (parser, "Invalid combination of ligature values");
return FALSE;
}
}
@@ -1010,7 +1048,7 @@ found:
values[3] = _gtk_css_font_variant_numeric_value_new (numeric);
if (values[3] == NULL)
{
_gtk_css_parser_error (parser, "Invalid combination of numeric values");
gtk_css_parser_error_value (parser, "Invalid combination of numeric values");
return FALSE;
}
}
@@ -1020,7 +1058,7 @@ found:
values[5] = _gtk_css_font_variant_east_asian_value_new (east_asian);
if (values[5] == NULL)
{
_gtk_css_parser_error (parser, "Invalid combination of east asian values");
gtk_css_parser_error_value (parser, "Invalid combination of east asian values");
return FALSE;
}
}
@@ -1034,7 +1072,7 @@ parse_all (GtkCssShorthandProperty *shorthand,
GtkCssValue **values,
GtkCssParser *parser)
{
_gtk_css_parser_error (parser, "The 'all' property can only be set to 'initial', 'inherit' or 'unset'");
gtk_css_parser_error_syntax (parser, "The 'all' property can only be set to 'initial', 'inherit' or 'unset'");
return FALSE;
}
@@ -1119,7 +1157,7 @@ pack_font_description (GtkCssShorthandProperty *shorthand,
v = (* query_func) (GTK_CSS_PROPERTY_FONT_WEIGHT, query_data);
if (v)
pango_font_description_set_weight (description, _gtk_css_font_weight_value_get (v));
pango_font_description_set_weight (description, _gtk_css_number_value_get (v, 100));
v = (* query_func) (GTK_CSS_PROPERTY_FONT_STRETCH, query_data);
if (v)
-1
View File
@@ -27,7 +27,6 @@
#include "gtkcssinheritvalueprivate.h"
#include "gtkcssinitialvalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcsssectionprivate.h"
#include "gtkcssshorthandpropertyprivate.h"
#include "gtkcssstringvalueprivate.h"
#include "gtkcssstylepropertyprivate.h"
+8 -3
View File
@@ -160,7 +160,7 @@ _gtk_css_string_value_parse (GtkCssParser *parser)
g_return_val_if_fail (parser != NULL, NULL);
s = _gtk_css_parser_read_string (parser);
s = gtk_css_parser_consume_string (parser);
if (s == NULL)
return NULL;
@@ -200,9 +200,14 @@ _gtk_css_ident_value_try_parse (GtkCssParser *parser)
g_return_val_if_fail (parser != NULL, NULL);
ident = _gtk_css_parser_try_ident (parser, TRUE);
if (ident == NULL)
if (!gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_IDENT))
return NULL;
ident = gtk_css_parser_consume_ident (parser);
if (ident == NULL)
{
g_assert_not_reached ();
}
return _gtk_css_ident_value_new_take (ident);
}
+1 -2
View File
@@ -29,7 +29,6 @@
#include "gtkcssinitialvalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcssrgbavalueprivate.h"
#include "gtkcsssectionprivate.h"
#include "gtkcssshorthandpropertyprivate.h"
#include "gtkcssstringvalueprivate.h"
#include "gtkcssfontfeaturesvalueprivate.h"
@@ -162,7 +161,7 @@ gtk_css_style_print (GtkCssStyle *style,
if (section)
{
g_string_append (string, " /* ");
_gtk_css_section_print (section, string);
gtk_css_section_print (section, string);
g_string_append (string, " */");
}
+1 -1
View File
@@ -21,9 +21,9 @@
#define __GTK_CSS_STYLE_PRIVATE_H__
#include <glib-object.h>
#include <gtk/css/gtkcss.h>
#include "gtk/gtkbitmaskprivate.h"
#include "gtk/gtkcsssection.h"
#include "gtk/gtkcssvalueprivate.h"
G_BEGIN_DECLS
+3 -3
View File
@@ -142,14 +142,14 @@ gtk_css_style_property_parse_value (GtkStyleProperty *property,
{
GtkCssStyleProperty *style_property = GTK_CSS_STYLE_PROPERTY (property);
if (_gtk_css_parser_try (parser, "initial", TRUE))
if (gtk_css_parser_try_ident (parser, "initial"))
{
/* the initial value can be explicitly specified with the
* initial keyword which all properties accept.
*/
return _gtk_css_initial_value_new ();
}
else if (_gtk_css_parser_try (parser, "inherit", TRUE))
else if (gtk_css_parser_try_ident (parser, "inherit"))
{
/* All properties accept the inherit value which
* explicitly specifies that the value will be determined
@@ -159,7 +159,7 @@ gtk_css_style_property_parse_value (GtkStyleProperty *property,
*/
return _gtk_css_inherit_value_new ();
}
else if (_gtk_css_parser_try (parser, "unset", TRUE))
else if (gtk_css_parser_try_ident (parser, "unset"))
{
/* If the cascaded value of a property is the unset keyword,
* then if it is an inherited property, this is treated as
+55 -40
View File
@@ -159,13 +159,16 @@ font_family_parse_one (GtkCssParser *parser)
{
char *name;
name = _gtk_css_parser_try_ident (parser, TRUE);
if (name)
if (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_IDENT))
{
GString *string = g_string_new (name);
GString *string = g_string_new (NULL);
name = gtk_css_parser_consume_ident (parser);
g_string_append (string, name);
g_free (name);
while ((name = _gtk_css_parser_try_ident (parser, TRUE)))
while (gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_IDENT))
{
name = gtk_css_parser_consume_ident (parser);
g_string_append_c (string, ' ');
g_string_append (string, name);
g_free (name);
@@ -174,7 +177,7 @@ font_family_parse_one (GtkCssParser *parser)
}
else
{
name = _gtk_css_parser_read_string (parser);
name = gtk_css_parser_consume_string (parser);
if (name == NULL)
return NULL;
}
@@ -224,7 +227,7 @@ font_style_parse (GtkCssStyleProperty *property,
GtkCssValue *value = _gtk_css_font_style_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown font style value");
return value;
}
@@ -242,10 +245,22 @@ static GtkCssValue *
font_weight_parse (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
GtkCssValue *value = _gtk_css_font_weight_value_try_parse (parser);
GtkCssValue *value;
value = gtk_css_font_weight_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
{
value = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_POSITIVE_ONLY);
if (value == NULL)
return NULL;
if (_gtk_css_number_value_get (value, 100) < 1 ||
_gtk_css_number_value_get (value, 100) > 1000)
{
gtk_css_parser_error_value (parser, "Font weight values must be between 1 and 1000");
g_clear_pointer (&value, gtk_css_value_unref);
}
}
return value;
}
@@ -256,7 +271,7 @@ font_weight_query (GtkCssStyleProperty *property,
GValue *value)
{
g_value_init (value, PANGO_TYPE_WEIGHT);
g_value_set_enum (value, _gtk_css_font_weight_value_get (css_value));
g_value_set_enum (value, _gtk_css_number_value_get (css_value, 100));
}
static GtkCssValue *
@@ -266,7 +281,7 @@ font_stretch_parse (GtkCssStyleProperty *property,
GtkCssValue *value = _gtk_css_font_stretch_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown font stretch value");
return value;
}
@@ -287,7 +302,7 @@ parse_border_style (GtkCssStyleProperty *property,
GtkCssValue *value = _gtk_css_border_style_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown border style value");
return value;
}
@@ -307,7 +322,7 @@ parse_css_area_one (GtkCssParser *parser)
GtkCssValue *value = _gtk_css_area_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown box value");
return value;
}
@@ -325,7 +340,7 @@ parse_one_css_direction (GtkCssParser *parser)
GtkCssValue *value = _gtk_css_direction_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown direction value");
return value;
}
@@ -360,7 +375,7 @@ parse_one_css_play_state (GtkCssParser *parser)
GtkCssValue *value = _gtk_css_play_state_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown play state value");
return value;
}
@@ -378,7 +393,7 @@ parse_one_css_fill_mode (GtkCssParser *parser)
GtkCssValue *value = _gtk_css_fill_mode_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown fill mode value");
return value;
}
@@ -414,7 +429,7 @@ icon_style_parse (GtkCssStyleProperty *property,
GtkCssValue *value = _gtk_css_icon_style_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown icon style value");
return value;
}
@@ -433,7 +448,7 @@ parse_text_decoration_line (GtkCssStyleProperty *property,
GtkCssValue *value = _gtk_css_text_decoration_line_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown text decoration line value");
return value;
}
@@ -445,7 +460,7 @@ parse_text_decoration_style (GtkCssStyleProperty *property,
GtkCssValue *value = _gtk_css_text_decoration_style_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown text decoration style value");
return value;
}
@@ -457,7 +472,7 @@ parse_font_kerning (GtkCssStyleProperty *property,
GtkCssValue *value = _gtk_css_font_kerning_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown font kerning value");
return value;
}
@@ -465,10 +480,10 @@ parse_font_kerning (GtkCssStyleProperty *property,
static gboolean
value_is_done_parsing (GtkCssParser *parser)
{
return _gtk_css_parser_is_eof (parser) ||
_gtk_css_parser_begins_with (parser, ',') ||
_gtk_css_parser_begins_with (parser, ';') ||
_gtk_css_parser_begins_with (parser, '}');
return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_COMMA) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SEMICOLON) ||
gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_CLOSE_CURLY);
}
static GtkCssValue *
@@ -485,7 +500,7 @@ parse_font_variant_ligatures (GtkCssStyleProperty *property,
parsed = _gtk_css_font_variant_ligature_try_parse_one (parser, ligatures);
if (parsed == 0 || parsed == ligatures)
{
_gtk_css_parser_error (parser, "Not a valid value");
gtk_css_parser_error_syntax (parser, "Not a valid value");
return NULL;
}
ligatures = parsed;
@@ -493,7 +508,7 @@ parse_font_variant_ligatures (GtkCssStyleProperty *property,
value = _gtk_css_font_variant_ligature_value_new (ligatures);
if (value == NULL)
_gtk_css_parser_error (parser, "Invalid combination of values");
gtk_css_parser_error_syntax (parser, "Invalid combination of values");
return value;
}
@@ -505,7 +520,7 @@ parse_font_variant_position (GtkCssStyleProperty *property,
GtkCssValue *value = _gtk_css_font_variant_position_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown font variant position value");
return value;
}
@@ -517,7 +532,7 @@ parse_font_variant_caps (GtkCssStyleProperty *property,
GtkCssValue *value = _gtk_css_font_variant_caps_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown font variant caps value");
return value;
}
@@ -536,7 +551,7 @@ parse_font_variant_numeric (GtkCssStyleProperty *property,
parsed = _gtk_css_font_variant_numeric_try_parse_one (parser, numeric);
if (parsed == 0 || parsed == numeric)
{
_gtk_css_parser_error (parser, "Not a valid value");
gtk_css_parser_error_syntax (parser, "Not a valid value");
return NULL;
}
numeric = parsed;
@@ -544,7 +559,7 @@ parse_font_variant_numeric (GtkCssStyleProperty *property,
value = _gtk_css_font_variant_numeric_value_new (numeric);
if (value == NULL)
_gtk_css_parser_error (parser, "Invalid combination of values");
gtk_css_parser_error_syntax (parser, "Invalid combination of values");
return value;
}
@@ -556,7 +571,7 @@ parse_font_variant_alternates (GtkCssStyleProperty *property,
GtkCssValue *value = _gtk_css_font_variant_alternate_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "unknown font variant alternate value");
return value;
}
@@ -575,7 +590,7 @@ parse_font_variant_east_asian (GtkCssStyleProperty *property,
parsed = _gtk_css_font_variant_east_asian_try_parse_one (parser, east_asian);
if (parsed == 0 || parsed == east_asian)
{
_gtk_css_parser_error (parser, "Not a valid value");
gtk_css_parser_error_syntax (parser, "Not a valid value");
return NULL;
}
east_asian = parsed;
@@ -583,7 +598,7 @@ parse_font_variant_east_asian (GtkCssStyleProperty *property,
value = _gtk_css_font_variant_east_asian_value_new (east_asian);
if (value == NULL)
_gtk_css_parser_error (parser, "Invalid combination of values");
gtk_css_parser_error_syntax (parser, "Invalid combination of values");
return value;
}
@@ -650,7 +665,7 @@ css_image_value_parse (GtkCssStyleProperty *property,
{
GtkCssImage *image;
if (_gtk_css_parser_try (parser, "none", TRUE))
if (gtk_css_parser_try_ident (parser, "none"))
image = NULL;
else
{
@@ -666,7 +681,7 @@ static GtkCssValue *
css_image_value_parse_with_builtin (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
if (_gtk_css_parser_try (parser, "builtin", TRUE))
if (gtk_css_parser_try_ident (parser, "builtin"))
return _gtk_css_image_value_new (gtk_css_image_builtin_new ());
return css_image_value_parse (property, parser);
@@ -730,7 +745,7 @@ border_image_repeat_parse (GtkCssStyleProperty *property,
if (value == NULL)
{
_gtk_css_parser_error (parser, "Not a valid value");
gtk_css_parser_error_syntax (parser, "Not a valid border repeat value");
return NULL;
}
@@ -780,7 +795,7 @@ transition_property_parse_one (GtkCssParser *parser)
if (value == NULL)
{
_gtk_css_parser_error (parser, "Expected an identifier");
gtk_css_parser_error_syntax (parser, "Expected an identifier");
return NULL;
}
@@ -817,7 +832,7 @@ transition_timing_function_parse (GtkCssStyleProperty *property,
static GtkCssValue *
iteration_count_parse_one (GtkCssParser *parser)
{
if (_gtk_css_parser_try (parser, "infinite", TRUE))
if (gtk_css_parser_try_ident (parser, "infinite"))
return _gtk_css_number_value_new (HUGE_VAL, GTK_CSS_NUMBER);
return _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER | GTK_CSS_POSITIVE_ONLY);
@@ -862,7 +877,7 @@ blend_mode_value_parse_one (GtkCssParser *parser)
GtkCssValue *value = _gtk_css_blend_mode_value_try_parse (parser);
if (value == NULL)
_gtk_css_parser_error (parser, "unknown value for property");
gtk_css_parser_error_syntax (parser, "Unknown blend mode value");
return value;
}
@@ -881,7 +896,7 @@ background_repeat_value_parse_one (GtkCssParser *parser)
if (value == NULL)
{
_gtk_css_parser_error (parser, "Not a valid value");
gtk_css_parser_error_syntax (parser, "Unknown repeat value");
return NULL;
}
@@ -1001,7 +1016,7 @@ _gtk_css_style_property_init_properties (void)
GTK_CSS_AFFECTS_TEXT_SIZE,
font_weight_parse,
font_weight_query,
_gtk_css_font_weight_value_new (PANGO_WEIGHT_NORMAL));
_gtk_css_number_value_new (PANGO_WEIGHT_NORMAL, GTK_CSS_NUMBER));
gtk_css_style_property_register ("font-stretch",
GTK_CSS_PROPERTY_FONT_STRETCH,
PANGO_TYPE_STRETCH,
+327 -320
View File
@@ -826,332 +826,102 @@ gtk_css_transform_value_is_none (const GtkCssValue *value)
return value->n_transforms == 0;
}
static gboolean
gtk_css_transform_parse (GtkCssTransform *transform,
GtkCssParser *parser)
static guint
gtk_css_transform_parse_float (GtkCssParser *parser,
guint n,
gpointer data)
{
if (_gtk_css_parser_try (parser, "matrix(", TRUE))
{
double xx, xy, x0, yx, yy, y0;
transform->type = GTK_CSS_TRANSFORM_MATRIX;
float *f = data;
double d;
/* FIXME: Improve error handling here */
if (!_gtk_css_parser_try_double (parser, &xx)
|| !_gtk_css_parser_try (parser, ",", TRUE)
|| !_gtk_css_parser_try_double (parser, &xy)
|| !_gtk_css_parser_try (parser, ",", TRUE)
|| !_gtk_css_parser_try_double (parser, &x0)
|| !_gtk_css_parser_try (parser, ",", TRUE)
|| !_gtk_css_parser_try_double (parser, &yx)
|| !_gtk_css_parser_try (parser, ",", TRUE)
|| !_gtk_css_parser_try_double (parser, &yy)
|| !_gtk_css_parser_try (parser, ",", TRUE)
|| !_gtk_css_parser_try_double (parser, &y0))
{
_gtk_css_parser_error (parser, "invalid syntax for matrix()");
return FALSE;
}
graphene_matrix_init_from_2d (&transform->matrix.matrix,
xx, yx, xy, yy, x0, y0);
}
else if (_gtk_css_parser_try (parser, "matrix3d(", TRUE))
{
float f[16];
double d;
guint i;
if (!gtk_css_parser_consume_number (parser, &d))
return 0;
transform->type = GTK_CSS_TRANSFORM_MATRIX;
f[n] = d;
return 1;
}
for (i = 0; i < 16; i++)
{
if (!_gtk_css_parser_try_double (parser, &d))
break;
f[i] = d;
static guint
gtk_css_transform_parse_length (GtkCssParser *parser,
guint n,
gpointer data)
{
GtkCssValue **values = data;
if (i < 15 && !_gtk_css_parser_try (parser, ",", TRUE))
break;
}
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (values[n] == NULL)
return 0;
if (i < 16)
{
/* FIXME: Improve error handling here */
_gtk_css_parser_error (parser, "invalid syntax for matrix3d()");
return FALSE;
}
graphene_matrix_init_from_float (&transform->matrix.matrix, f);
}
else if (_gtk_css_parser_try (parser, "translate(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_TRANSLATE;
return 1;
}
transform->translate.x = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (transform->translate.x == NULL)
return FALSE;
static guint
gtk_css_transform_parse_angle (GtkCssParser *parser,
guint n,
gpointer data)
{
GtkCssValue **values = data;
if (_gtk_css_parser_try (parser, ",", TRUE))
{
transform->translate.y = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (transform->translate.y == NULL)
{
_gtk_css_value_unref (transform->translate.x);
return FALSE;
}
}
else
{
transform->translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
}
transform->translate.z = _gtk_css_number_value_new (0, GTK_CSS_PX);
}
else if (_gtk_css_parser_try (parser, "translateX(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_TRANSLATE;
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (values[n] == NULL)
return 0;
transform->translate.x = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (transform->translate.x == NULL)
return FALSE;
transform->translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
transform->translate.z = _gtk_css_number_value_new (0, GTK_CSS_PX);
}
else if (_gtk_css_parser_try (parser, "translateY(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_TRANSLATE;
return 1;
}
transform->translate.y = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (transform->translate.y == NULL)
return FALSE;
transform->translate.x = _gtk_css_number_value_new (0, GTK_CSS_PX);
transform->translate.z = _gtk_css_number_value_new (0, GTK_CSS_PX);
}
else if (_gtk_css_parser_try (parser, "translateZ(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_TRANSLATE;
static guint
gtk_css_transform_parse_number (GtkCssParser *parser,
guint n,
gpointer data)
{
GtkCssValue **values = data;
transform->translate.z = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (transform->translate.z == NULL)
return FALSE;
transform->translate.x = _gtk_css_number_value_new (0, GTK_CSS_PX);
transform->translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
}
else if (_gtk_css_parser_try (parser, "translate3d(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_TRANSLATE;
values[n] = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (values[n] == NULL)
return 0;
transform->translate.x = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (transform->translate.x != NULL)
{
transform->translate.y = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (transform->translate.y != NULL)
{
transform->translate.z = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (transform->translate.z != NULL)
goto out;
}
_gtk_css_value_unref (transform->translate.y);
}
_gtk_css_value_unref (transform->translate.x);
return FALSE;
}
else if (_gtk_css_parser_try (parser, "scale(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_SCALE;
return 1;
}
transform->scale.x = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->scale.x == NULL)
return FALSE;
if (_gtk_css_parser_try (parser, ",", TRUE))
{
transform->scale.y = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->scale.y == NULL)
{
_gtk_css_value_unref (transform->scale.x);
return FALSE;
}
}
else
{
transform->scale.y = _gtk_css_value_ref (transform->scale.x);
}
transform->scale.z = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
}
else if (_gtk_css_parser_try (parser, "scaleX(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_SCALE;
transform->scale.x = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->scale.x == NULL)
return FALSE;
transform->scale.y = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
transform->scale.z = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
}
else if (_gtk_css_parser_try (parser, "scaleY(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_SCALE;
transform->scale.y = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->scale.y == NULL)
return FALSE;
transform->scale.x = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
transform->scale.z = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
}
else if (_gtk_css_parser_try (parser, "scaleZ(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_SCALE;
transform->scale.z = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->scale.z == NULL)
return FALSE;
transform->scale.x = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
transform->scale.y = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
}
else if (_gtk_css_parser_try (parser, "scale3d(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_SCALE;
transform->scale.x = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->scale.x != NULL)
{
transform->scale.y = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->scale.y != NULL)
{
transform->scale.z = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->scale.z != NULL)
goto out;
}
_gtk_css_value_unref (transform->scale.y);
}
_gtk_css_value_unref (transform->scale.x);
return FALSE;
}
else if (_gtk_css_parser_try (parser, "rotate(", TRUE) ||
_gtk_css_parser_try (parser, "rotateZ(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_ROTATE;
transform->rotate.angle = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (transform->rotate.angle == NULL)
return FALSE;
transform->rotate.x = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
transform->rotate.y = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
transform->rotate.z = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
}
else if (_gtk_css_parser_try (parser, "rotateX(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_ROTATE;
transform->rotate.angle = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (transform->rotate.angle == NULL)
return FALSE;
transform->rotate.x = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
transform->rotate.y = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
transform->rotate.z = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
}
else if (_gtk_css_parser_try (parser, "rotateY(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_ROTATE;
transform->rotate.angle = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (transform->rotate.angle == NULL)
return FALSE;
transform->rotate.x = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
transform->rotate.y = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
transform->rotate.z = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
}
else if (_gtk_css_parser_try (parser, "rotate3d(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_ROTATE;
static guint
gtk_css_transform_parse_rotate3d (GtkCssParser *parser,
guint n,
gpointer data)
{
GtkCssTransform *transform = data;
switch (n)
{
case 0:
transform->rotate.x = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->rotate.x != NULL)
{
transform->rotate.y = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->rotate.y != NULL)
{
transform->rotate.z = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->rotate.z != NULL)
{
transform->rotate.angle = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (transform->rotate.angle != NULL)
goto out;
}
_gtk_css_value_unref (transform->rotate.z);
}
_gtk_css_value_unref (transform->rotate.y);
}
_gtk_css_value_unref (transform->rotate.x);
return FALSE;
}
else if (_gtk_css_parser_try (parser, "skew(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_SKEW;
if (transform->rotate.x == NULL)
return 0;
break;
transform->skew.x = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (transform->skew.x == NULL)
return FALSE;
case 1:
transform->rotate.y = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->rotate.y == NULL)
return 0;
break;
if (_gtk_css_parser_try (parser, ",", TRUE))
{
transform->skew.y = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (transform->skew.y == NULL)
{
_gtk_css_value_unref (transform->skew.x);
return FALSE;
}
}
else
{
transform->skew.y = _gtk_css_number_value_new (0, GTK_CSS_DEG);
}
}
else if (_gtk_css_parser_try (parser, "skewX(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_SKEW_X;
case 2:
transform->rotate.z = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
if (transform->rotate.z == NULL)
return 0;
break;
transform->skew_x.skew = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (transform->skew_x.skew == NULL)
return FALSE;
}
else if (_gtk_css_parser_try (parser, "skewY(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_SKEW_Y;
case 3:
transform->rotate.angle = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (transform->rotate.angle == NULL)
return 0;
break;
transform->skew_y.skew = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_ANGLE);
if (transform->skew_y.skew == NULL)
return FALSE;
}
else if (_gtk_css_parser_try (parser, "perspective(", TRUE))
{
transform->type = GTK_CSS_TRANSFORM_PERSPECTIVE;
default:
g_assert_not_reached();
return 0;
}
transform->perspective.depth = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
if (transform->perspective.depth == NULL)
return FALSE;
}
else
{
_gtk_css_parser_error (parser, "unknown syntax for transform");
return FALSE;
}
out:
if (!_gtk_css_parser_try (parser, ")", TRUE))
{
gtk_css_transform_clear (transform);
_gtk_css_parser_error (parser, "Expected closing ')'");
return FALSE;
}
return TRUE;
return 1;
}
GtkCssValue *
@@ -1161,25 +931,254 @@ _gtk_css_transform_value_parse (GtkCssParser *parser)
GArray *array;
guint i;
if (_gtk_css_parser_try (parser, "none", TRUE))
if (gtk_css_parser_try_ident (parser, "none"))
return _gtk_css_transform_value_new_none ();
array = g_array_new (FALSE, FALSE, sizeof (GtkCssTransform));
do {
GtkCssTransform transform;
while (TRUE)
{
GtkCssTransform transform;
if (!gtk_css_transform_parse (&transform, parser))
{
for (i = 0; i < array->len; i++)
{
gtk_css_transform_clear (&g_array_index (array, GtkCssTransform, i));
}
g_array_free (array, TRUE);
return NULL;
}
g_array_append_val (array, transform);
} while (!_gtk_css_parser_begins_with (parser, ';'));
if (gtk_css_parser_has_function (parser, "matrix"))
{
float f[6];
if (!gtk_css_parser_consume_function (parser, 6, 6, gtk_css_transform_parse_float, f))
goto fail;
transform.type = GTK_CSS_TRANSFORM_MATRIX;
graphene_matrix_init_from_2d (&transform.matrix.matrix, f[0], f[1], f[2], f[3], f[4], f[5]);
}
else if (gtk_css_parser_has_function (parser, "matrix3d"))
{
float f[16];
if (!gtk_css_parser_consume_function (parser, 16, 16, gtk_css_transform_parse_float, f))
goto fail;
transform.type = GTK_CSS_TRANSFORM_MATRIX;
graphene_matrix_init_from_float (&transform.matrix.matrix, f);
}
else if (gtk_css_parser_has_function (parser, "perspective"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_length, &transform.perspective.depth))
goto fail;
transform.type = GTK_CSS_TRANSFORM_PERSPECTIVE;
}
else if (gtk_css_parser_has_function (parser, "rotate") ||
gtk_css_parser_has_function (parser, "rotateZ"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_angle, &transform.rotate.angle))
goto fail;
transform.type = GTK_CSS_TRANSFORM_ROTATE;
transform.rotate.x = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
transform.rotate.y = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
transform.rotate.z = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
}
else if (gtk_css_parser_has_function (parser, "rotate3d"))
{
if (!gtk_css_parser_consume_function (parser, 4, 4, gtk_css_transform_parse_rotate3d, &transform))
{
g_clear_pointer (&transform.rotate.x, gtk_css_value_unref);
g_clear_pointer (&transform.rotate.y, gtk_css_value_unref);
g_clear_pointer (&transform.rotate.z, gtk_css_value_unref);
g_clear_pointer (&transform.rotate.angle, gtk_css_value_unref);
goto fail;
}
transform.type = GTK_CSS_TRANSFORM_ROTATE;
}
else if (gtk_css_parser_has_function (parser, "rotateX"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_angle, &transform.rotate.angle))
goto fail;
transform.type = GTK_CSS_TRANSFORM_ROTATE;
transform.rotate.x = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
transform.rotate.y = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
transform.rotate.z = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
}
else if (gtk_css_parser_has_function (parser, "rotateY"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_angle, &transform.rotate.angle))
goto fail;
transform.type = GTK_CSS_TRANSFORM_ROTATE;
transform.rotate.x = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
transform.rotate.y = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
transform.rotate.z = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
}
else if (gtk_css_parser_has_function (parser, "scale"))
{
GtkCssValue *values[2] = { NULL, NULL };
if (!gtk_css_parser_consume_function (parser, 1, 2, gtk_css_transform_parse_number, values))
{
g_clear_pointer (&values[0], gtk_css_value_unref);
g_clear_pointer (&values[1], gtk_css_value_unref);
goto fail;
}
transform.type = GTK_CSS_TRANSFORM_SCALE;
transform.scale.x = values[0];
if (values[1])
transform.scale.y = values[1];
else
transform.scale.y = gtk_css_value_ref (values[0]);
transform.scale.z = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
}
else if (gtk_css_parser_has_function (parser, "scale3d"))
{
GtkCssValue *values[3] = { NULL, NULL };
if (!gtk_css_parser_consume_function (parser, 3, 3, gtk_css_transform_parse_number, values))
{
g_clear_pointer (&values[0], gtk_css_value_unref);
g_clear_pointer (&values[1], gtk_css_value_unref);
g_clear_pointer (&values[2], gtk_css_value_unref);
goto fail;
}
transform.type = GTK_CSS_TRANSFORM_SCALE;
transform.scale.x = values[0];
transform.scale.y = values[1];
transform.scale.z = values[2];
}
else if (gtk_css_parser_has_function (parser, "scaleX"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_number, &transform.scale.x))
goto fail;
transform.type = GTK_CSS_TRANSFORM_SCALE;
transform.scale.y = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
transform.scale.z = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
}
else if (gtk_css_parser_has_function (parser, "scaleY"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_number, &transform.scale.y))
goto fail;
transform.type = GTK_CSS_TRANSFORM_SCALE;
transform.scale.x = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
transform.scale.z = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
}
else if (gtk_css_parser_has_function (parser, "scaleZ"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_number, &transform.scale.z))
goto fail;
transform.type = GTK_CSS_TRANSFORM_SCALE;
transform.scale.x = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
transform.scale.y = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
}
else if (gtk_css_parser_has_function (parser, "skew"))
{
GtkCssValue *values[2] = { NULL, NULL };
if (!gtk_css_parser_consume_function (parser, 2, 2, gtk_css_transform_parse_angle, values))
{
g_clear_pointer (&values[0], gtk_css_value_unref);
g_clear_pointer (&values[1], gtk_css_value_unref);
goto fail;
}
transform.type = GTK_CSS_TRANSFORM_SKEW;
transform.skew.x = values[0];
transform.skew.y = values[1];
}
else if (gtk_css_parser_has_function (parser, "skewX"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_angle, &transform.skew_x.skew))
goto fail;
transform.type = GTK_CSS_TRANSFORM_SKEW_X;
}
else if (gtk_css_parser_has_function (parser, "skewY"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_angle, &transform.skew_y.skew))
goto fail;
transform.type = GTK_CSS_TRANSFORM_SKEW_Y;
}
else if (gtk_css_parser_has_function (parser, "translate"))
{
GtkCssValue *values[2] = { NULL, NULL };
if (!gtk_css_parser_consume_function (parser, 1, 2, gtk_css_transform_parse_length, values))
{
g_clear_pointer (&values[0], gtk_css_value_unref);
g_clear_pointer (&values[1], gtk_css_value_unref);
goto fail;
}
transform.type = GTK_CSS_TRANSFORM_TRANSLATE;
transform.translate.x = values[0];
if (values[1])
transform.translate.y = values[1];
else
transform.translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
transform.translate.z = _gtk_css_number_value_new (0, GTK_CSS_PX);
}
else if (gtk_css_parser_has_function (parser, "translate3d"))
{
GtkCssValue *values[3] = { NULL, NULL };
if (!gtk_css_parser_consume_function (parser, 3, 3, gtk_css_transform_parse_length, values))
{
g_clear_pointer (&values[0], gtk_css_value_unref);
g_clear_pointer (&values[1], gtk_css_value_unref);
g_clear_pointer (&values[2], gtk_css_value_unref);
goto fail;
}
transform.type = GTK_CSS_TRANSFORM_TRANSLATE;
transform.translate.x = values[0];
transform.translate.y = values[1];
transform.translate.z = values[2];
}
else if (gtk_css_parser_has_function (parser, "translateX"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_length, &transform.translate.x))
goto fail;
transform.type = GTK_CSS_TRANSFORM_TRANSLATE;
transform.translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
transform.translate.z = _gtk_css_number_value_new (0, GTK_CSS_PX);
}
else if (gtk_css_parser_has_function (parser, "translateY"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_length, &transform.translate.y))
goto fail;
transform.type = GTK_CSS_TRANSFORM_TRANSLATE;
transform.translate.x = _gtk_css_number_value_new (0, GTK_CSS_PX);
transform.translate.z = _gtk_css_number_value_new (0, GTK_CSS_PX);
}
else if (gtk_css_parser_has_function (parser, "translateZ"))
{
if (!gtk_css_parser_consume_function (parser, 1, 1, gtk_css_transform_parse_length, &transform.translate.z))
goto fail;
transform.type = GTK_CSS_TRANSFORM_TRANSLATE;
transform.translate.x = _gtk_css_number_value_new (0, GTK_CSS_PX);
transform.translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
}
else
{
break;
}
g_array_append_val (array, transform);
}
if (array->len == 0)
{
gtk_css_parser_error_syntax (parser, "Expected a transform");
goto fail;
}
value = gtk_css_transform_value_alloc (array->len);
memcpy (value->transforms, array->data, sizeof (GtkCssTransform) * array->len);
@@ -1187,6 +1186,14 @@ _gtk_css_transform_value_parse (GtkCssParser *parser)
g_array_free (array, TRUE);
return value;
fail:
for (i = 0; i < array->len; i++)
{
gtk_css_transform_clear (&g_array_index (array, GtkCssTransform, i));
}
g_array_free (array, TRUE);
return NULL;
}
GskTransform *
+1 -1
View File
@@ -36,7 +36,7 @@ gtk_custom_layout_get_request_mode (GtkLayoutManager *manager,
if (self->request_mode_func != NULL)
return self->request_mode_func (widget);
return GTK_SIZE_REQUEST_CONSTANT_SIZE;
return GTK_LAYOUT_MANAGER_CLASS (gtk_custom_layout_parent_class)->get_request_mode (manager, widget);
}
static void
+1 -1
View File
@@ -3117,7 +3117,7 @@ gtk_entry_ensure_progress_widget (GtkEntry *entry)
priv->progress_widget = g_object_new (GTK_TYPE_PROGRESS_BAR,
"css-name", "progress",
NULL);
gtk_widget_set_can_pick (priv->progress_widget, FALSE);
gtk_widget_set_can_target (priv->progress_widget, FALSE);
gtk_widget_set_parent (priv->progress_widget, GTK_WIDGET (entry));
+14
View File
@@ -1040,4 +1040,18 @@ typedef enum {
GTK_PLACES_OPEN_NEW_WINDOW = 1 << 2
} GtkPlacesOpenFlags;
/**
* GtkPickFlags:
* @GTK_PICK_DEFAULT: The default behavior, include widgets that are receiving events
* @GTK_PICK_INSENSITIVE: Include widgets that are insensitive
* @GTK_PICK_NON_TARGETABLE: Include widgets that are marked as non-targetable. See #GtkWidget::can-target
*
* Flags that influence the behavior of gtk_widget_pick()
*/
typedef enum {
GTK_PICK_DEFAULT = 0,
GTK_PICK_INSENSITIVE = 1 << 0,
GTK_PICK_NON_TARGETABLE = 1 << 1
} GtkPickFlags;
#endif /* __GTK_ENUMS_H__ */

Some files were not shown because too many files have changed in this diff Show More