[gtk/wip/otte/css: 28/28] rgba: Add gdk_rgba_parser_parse()



commit 8182658258c4c7c4e570cc1fa9c3c2ee3a2810dc
Author: Benjamin Otte <otte redhat com>
Date:   Sat Apr 6 02:40:29 2019 +0200

    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.

 gdk/gdkrgba.c        | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 gdk/gdkrgbaprivate.h |  33 ++++++++++
 gdk/meson.build      |   5 +-
 3 files changed, 205 insertions(+), 3 deletions(-)
---
diff --git a/gdk/gdkrgba.c b/gdk/gdkrgba.c
index 8e36523dc2..7e59548739 100644
--- a/gdk/gdkrgba.c
+++ b/gdk/gdkrgba.c
@@ -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,169 @@ 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;
+
+  if (arg == 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;
+    }
+  else if (arg == 1)
+    {
+      if (!parse_color_channel_value (parser, &rgba->green, rgba->alpha != 0.0))
+        return 0;
+    }
+  else if (arg == 2)
+    {
+      if (!parse_color_channel_value (parser, &rgba->blue, rgba->alpha != 0.0))
+        return 0;
+    }
+  else if (arg == 3)
+    {
+      if (!gtk_css_parser_consume_number (parser, &rgba->alpha))
+        return FALSE;
+
+      rgba->alpha = CLAMP (rgba->alpha, 0.0, 1.0);
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+
+  return 1;
+}
+
+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' }))
+              return TRUE;
+            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] }))
+              return TRUE;
+            break;
+
+          case 6:
+            if (rgba_init_chars (rgba, (char[8]) {s[0], s[1], s[2], s[3], s[4], s[5], 'F', 'F' }))
+              return TRUE;
+            break;
+
+          case 8:
+            if (rgba_init_chars (rgba, s))
+              return TRUE;
+            break;
+
+          default:
+            break;
+        }
+
+      gtk_css_parser_error_value (parser, "Hash code is not a valid hex color.");
+      return FALSE;
+    }
+  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_value (parser, "\"%s\" is not a known 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;
+    }
+}
+
diff --git a/gdk/gdkrgbaprivate.h b/gdk/gdkrgbaprivate.h
new file mode 100644
index 0000000000..58470e04c9
--- /dev/null
+++ b/gdk/gdkrgbaprivate.h
@@ -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
diff --git a/gdk/meson.build b/gdk/meson.build
index 44170dbae8..b2bf69620a 100644
--- a/gdk/meson.build
+++ b/gdk/meson.build
@@ -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])


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]