[cogl/wip/sparse: 1/5] bindings: Starts to add v8 JavaScript bindings



commit d6a44e5941abae8964d452c034e96b11e6a1bf35
Author: Robert Bragg <robert linux intel com>
Date:   Fri Mar 9 23:15:15 2012 +0000

    bindings: Starts to add v8 JavaScript bindings
    
    This starts to add support for v8 JavaScript bindings for Cogl.
    
    Since JavaScript bindings only make sense as an embedded language this
    patch adds a minimal cogl-v8 program that is used to bootstrap an
    embedding environment that is initially also responsible for creating
    a CoglContext and a single CoglOnscreen framebuffer, this will no
    doubt change as the bindings evolve.
    
    Eventually we may provide a cogl-v8 sub-library that might have a public
    api like cogl_v8_bind (v8::Handle<v8::ObjectTemplate> global) that
    can add the bindings to an object and context created by something else
    (such as node.js for example).
    
    At this point the api coverage is basically zero, but the aim next is
    to look at auto generating bindings for most of Cogl's trivial methods.

 Makefile.am                      |    4 +
 bindings/Makefile.am             |    3 +
 bindings/v8/Makefile.am          |   24 +
 bindings/v8/cogl-v8-color.cc     |  410 ++++++++++
 bindings/v8/cogl-v8-color.h      |   29 +
 bindings/v8/cogl-v8-pipeline.cc  |  156 ++++
 bindings/v8/cogl-v8-pipeline.h   |   33 +
 bindings/v8/cogl-v8-primitive.cc |  116 +++
 bindings/v8/cogl-v8-primitive.h  |   33 +
 bindings/v8/cogl-v8.cc           |  193 +++++
 bindings/v8/cogl-v8.h            |   57 ++
 bindings/v8/color-table.h        | 1516 ++++++++++++++++++++++++++++++++++++++
 bindings/v8/test.js              |   15 +
 build/autotools/v8.m4            |  142 ++++
 configure.ac                     |   26 +
 15 files changed, 2757 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index bbb16ae..845f332 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,6 +6,10 @@ endif
 
 SUBDIRS += examples doc po build
 
+if SUPPORT_V8_BINDINGS
+SUBDIRS += bindings
+endif
+
 ACLOCAL_AMFLAGS = -I build/autotools ${ACLOCAL_FLAGS}
 
 EXTRA_DIST = \
diff --git a/bindings/Makefile.am b/bindings/Makefile.am
new file mode 100644
index 0000000..f6b1ec7
--- /dev/null
+++ b/bindings/Makefile.am
@@ -0,0 +1,3 @@
+if SUPPORT_V8_BINDINGS
+SUBDIRS = v8
+endif
diff --git a/bindings/v8/Makefile.am b/bindings/v8/Makefile.am
new file mode 100644
index 0000000..0098854
--- /dev/null
+++ b/bindings/v8/Makefile.am
@@ -0,0 +1,24 @@
+INCLUDES = \
+	-I$(top_srcdir)
+
+AM_CXXFLAGS = \
+	$(COGL_DEP_CFLAGS) \
+	$(COGL_EXTRA_CFLAGS) \
+	-DCOGL_ENABLE_EXPERIMENTAL_2_0_API
+
+noinst_PROGRAMS = cogl-v8
+
+cogl_v8_SOURCES = \
+	cogl-v8.cc \
+	cogl-v8-pipeline.h \
+	cogl-v8-pipeline.cc \
+	cogl-v8-color.h \
+	cogl-v8-color.cc \
+	cogl-v8-primitive.h \
+	cogl-v8-primitive.cc \
+	$(NULL)
+cogl_v8_CPPFLAGS= V8_CPPFLAGS@
+cogl_v8_LDADD = \
+	$(COGL_DEP_LIBS) \
+	$(top_builddir)/cogl/libcogl.la \
+	@V8_LDFLAGS@
diff --git a/bindings/v8/cogl-v8-color.cc b/bindings/v8/cogl-v8-color.cc
new file mode 100644
index 0000000..e2c60d7
--- /dev/null
+++ b/bindings/v8/cogl-v8-color.cc
@@ -0,0 +1,410 @@
+/*
+ * Cogl V8 Bindings
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * 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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include <glib.h>
+
+#include <cogl/cogl.h>
+
+#include "color-table.h"
+
+static inline void
+skip_whitespace (char **str)
+{
+  while (g_ascii_isspace (**str))
+    *str += 1;
+}
+
+static inline void
+parse_rgb_value (char *str,
+                 float *color,
+                 char **endp)
+{
+  float number;
+  char *p;
+
+  skip_whitespace (&str);
+
+  number = g_ascii_strtod (str, endp);
+
+  p = *endp;
+
+  skip_whitespace (&p);
+
+  if (*p == '%')
+    {
+      *endp = p + 1;
+
+      *color = CLAMP (number / 100.0, 0.0, 1.0);
+    }
+  else
+    *color = CLAMP (number, 0.0, 1.0);
+}
+
+static gboolean
+parse_rgba (CoglColor *color,
+            char *str,
+            gboolean has_alpha)
+{
+  float red, green, blue, alpha;
+
+  skip_whitespace (&str);
+
+  if (*str != '(')
+    return FALSE;
+
+  str += 1;
+
+  /* red */
+  parse_rgb_value (str, &red, &str);
+  skip_whitespace (&str);
+  if (*str != ',')
+    return FALSE;
+
+  str += 1;
+
+  /* green */
+  parse_rgb_value (str, &green, &str);
+  skip_whitespace (&str);
+  if (*str != ',')
+    return FALSE;
+
+  str += 1;
+
+  /* blue */
+  parse_rgb_value (str, &blue, &str);
+  skip_whitespace (&str);
+
+  /* alpha (optional); since the alpha channel value can only
+   * be between 0 and 1 we don't use the parse_rgb_value()
+   * function
+   */
+  if (has_alpha)
+    {
+      if (*str != ',')
+        return FALSE;
+
+      str += 1;
+
+      skip_whitespace (&str);
+      alpha = g_ascii_strtod (str, &str);
+      alpha = CLAMP (alpha, 0.0, 1.0);
+    }
+  else
+    alpha = 1.0;
+
+  skip_whitespace (&str);
+  if (*str != ')')
+    return FALSE;
+
+  cogl_color_init_from_4f (color, red, green, blue, alpha);
+
+  return TRUE;
+}
+
+static void
+_cogl_color_init_from_hls (CoglColor *color,
+                           float hue,
+                           float luminance,
+                           float saturation)
+{
+  float tmp1, tmp2;
+  float tmp3[3];
+  float clr[3];
+  int   i;
+
+  hue /= 360.0;
+
+  if (saturation == 0)
+    {
+      cogl_color_init_from_4f (color, luminance, luminance, luminance, 1.0);
+      return;
+    }
+
+  if (luminance <= 0.5)
+    tmp2 = luminance * (1.0 + saturation);
+  else
+    tmp2 = luminance + saturation - (luminance * saturation);
+
+  tmp1 = 2.0 * luminance - tmp2;
+
+  tmp3[0] = hue + 1.0 / 3.0;
+  tmp3[1] = hue;
+  tmp3[2] = hue - 1.0 / 3.0;
+
+  for (i = 0; i < 3; i++)
+    {
+      if (tmp3[i] < 0)
+        tmp3[i] += 1.0;
+
+      if (tmp3[i] > 1)
+        tmp3[i] -= 1.0;
+
+      if (6.0 * tmp3[i] < 1.0)
+        clr[i] = tmp1 + (tmp2 - tmp1) * tmp3[i] * 6.0;
+      else if (2.0 * tmp3[i] < 1.0)
+        clr[i] = tmp2;
+      else if (3.0 * tmp3[i] < 2.0)
+        clr[i] = (tmp1 + (tmp2 - tmp1) * ((2.0 / 3.0) - tmp3[i]) * 6.0);
+      else
+        clr[i] = tmp1;
+    }
+
+  cogl_color_init_from_4f (color, clr[0], clr[1], clr[2], 1.0);
+}
+
+static gboolean
+parse_hsla (CoglColor *color,
+            char *str,
+            gboolean has_alpha)
+{
+  float number;
+  float h, l, s, a;
+
+  skip_whitespace (&str);
+
+  if (*str != '(')
+    return FALSE;
+
+  str += 1;
+
+  /* hue */
+  skip_whitespace (&str);
+  /* we don't do any angle normalization here because
+   * clutter_color_from_hls() will do it for us
+   */
+  number = g_ascii_strtod (str, &str);
+  skip_whitespace (&str);
+  if (*str != ',')
+    return FALSE;
+
+  h = number;
+
+  str += 1;
+
+  /* saturation */
+  skip_whitespace (&str);
+  number = g_ascii_strtod (str, &str);
+  skip_whitespace (&str);
+  if (*str != '%')
+    return FALSE;
+
+  str += 1;
+
+  s = CLAMP (number / 100.0, 0.0, 1.0);
+  skip_whitespace (&str);
+  if (*str != ',')
+    return FALSE;
+
+  str += 1;
+
+  /* luminance */
+  skip_whitespace (&str);
+  number = g_ascii_strtod (str, &str);
+  skip_whitespace (&str);
+  if (*str != '%')
+    return FALSE;
+
+  str += 1;
+
+  l = CLAMP (number / 100.0, 0.0, 1.0);
+  skip_whitespace (&str);
+
+  /* alpha (optional); since the alpha channel value can only
+   * be between 0 and 1 we don't use the parse_rgb_value()
+   * function
+   */
+  if (has_alpha)
+    {
+      if (*str != ',')
+        return FALSE;
+
+      str += 1;
+
+      skip_whitespace (&str);
+      number = g_ascii_strtod (str, &str);
+
+      a = CLAMP (number, 0.0, 1.0);
+    }
+  else
+    a = 1.0;
+
+  skip_whitespace (&str);
+  if (*str != ')')
+    return FALSE;
+
+  _cogl_color_init_from_hls (color, h, l, s);
+  cogl_color_set_alpha (color, a);
+
+  return TRUE;
+}
+
+gboolean
+_cogl_color_init_from_string (CoglColor *color,
+                              const char *str,
+                              GHashTable **colors_hash)
+{
+  void *color_index_ptr;
+
+  g_return_val_if_fail (color != NULL, FALSE);
+  g_return_val_if_fail (str != NULL, FALSE);
+
+  if (strncmp (str, "rgb", 3) == 0)
+    {
+      char *s = (char *)str;
+      gboolean res;
+
+      if (strncmp (str, "rgba", 4) == 0)
+        res = parse_rgba (color, s + 4, TRUE);
+      else
+        res = parse_rgba (color, s + 3, FALSE);
+
+      return res;
+    }
+
+  if (strncmp (str, "hsl", 3) == 0)
+    {
+      char *s = (char *)str;
+      gboolean res;
+
+      if (strncmp (str, "hsla", 4) == 0)
+        res = parse_hsla (color, s + 4, TRUE);
+      else
+        res = parse_hsla (color, s + 3, FALSE);
+
+      return res;
+    }
+
+  /* if the string contains a color encoded using the hexadecimal
+   * notations (#rrggbbaa or #rgba) we attempt a rough pass at
+   * parsing the color ourselves, as we need the alpha channel that
+   * Pango can't retrieve.
+   */
+  if (str[0] == '#' && str[1] != '\0')
+    {
+      guint8 red, green, blue, alpha;
+      size_t length = strlen (str + 1);
+      unsigned int result;
+
+      if (sscanf (str + 1, "%x", &result) == 1)
+        {
+          switch (length)
+            {
+            case 8: /* rrggbbaa */
+              red   = (result >> 24) & 0xff;
+              green = (result >> 16) & 0xff;
+              blue  = (result >>  8) & 0xff;
+
+              alpha = result & 0xff;
+
+              cogl_color_init_from_4ub (color, red, green, blue, alpha);
+
+              return TRUE;
+
+            case 6: /* #rrggbb */
+              red   = (result >> 16) & 0xff;
+              green = (result >>  8) & 0xff;
+              blue  = result & 0xff;
+
+              alpha = 0xff;
+
+              cogl_color_init_from_4ub (color, red, green, blue, alpha);
+
+              return TRUE;
+
+            case 4: /* #rgba */
+              red   = ((result >> 12) & 0xf);
+              green = ((result >>  8) & 0xf);
+              blue  = ((result >>  4) & 0xf);
+              alpha = result & 0xf;
+
+              red   = (red   << 4) | red;
+              green = (green << 4) | green;
+              blue  = (blue  << 4) | blue;
+              alpha = (alpha << 4) | alpha;
+
+              cogl_color_init_from_4ub (color, red, green, blue, alpha);
+
+              return TRUE;
+
+            case 3: /* #rgb */
+              red   = ((result >>  8) & 0xf);
+              green = ((result >>  4) & 0xf);
+              blue  = result & 0xf;
+
+              red   = (red   << 4) | red;
+              green = (green << 4) | green;
+              blue  = (blue  << 4) | blue;
+
+              alpha = 0xff;
+
+              cogl_color_init_from_4ub (color, red, green, blue, alpha);
+
+              return TRUE;
+
+            default:
+              return FALSE;
+            }
+        }
+    }
+
+  /* fall back to X11-style named colors; see:
+   *
+   *   http://en.wikipedia.org/wiki/X11_color_names
+   */
+
+  if (!*colors_hash)
+    {
+      int i, n_colors;
+
+      *colors_hash = g_hash_table_new (g_direct_hash, g_int_equal);
+
+      n_colors = G_N_ELEMENTS (color_names);
+      for (i = 0; i < n_colors; i++)
+        {
+          const char *interned = g_intern_string (color_names[i]);
+          g_hash_table_insert (*colors_hash, (gpointer)interned, GINT_TO_POINTER (i + 1));
+        }
+    }
+
+  color_index_ptr = g_hash_table_lookup (*colors_hash,
+                                         g_intern_string (str));
+  if (color_index_ptr)
+    {
+      /* Since we can't store 0 in the hash table without creating an ambiguity
+       * when retrieving the value back the indices stored are all offset by
+       * one. */
+      int color_index = GPOINTER_TO_INT (color_index_ptr) - 1;
+      cogl_color_init_from_4ub (color,
+                                color_entries[color_index].red,
+                                color_entries[color_index].green,
+                                color_entries[color_index].blue,
+                                255);
+      return TRUE;
+    }
+
+  return FALSE;
+}
diff --git a/bindings/v8/cogl-v8-color.h b/bindings/v8/cogl-v8-color.h
new file mode 100644
index 0000000..628982c
--- /dev/null
+++ b/bindings/v8/cogl-v8-color.h
@@ -0,0 +1,29 @@
+/*
+ * Cogl V8 Bindings
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * 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 __COGL_V8_COLOR_H__
+#define __COGL_V8_COLOR_H__
+
+gboolean
+_cogl_color_init_from_string (CoglColor *color,
+                              const char *str,
+                              GHashTable **colors_hash);
+
+#endif /* __COGL_V8_COLOR_H__ */
diff --git a/bindings/v8/cogl-v8-pipeline.cc b/bindings/v8/cogl-v8-pipeline.cc
new file mode 100644
index 0000000..9afff3d
--- /dev/null
+++ b/bindings/v8/cogl-v8-pipeline.cc
@@ -0,0 +1,156 @@
+/*
+ * Cogl V8 Bindings
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * 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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <v8.h>
+
+#include <cogl/cogl.h>
+
+#include "cogl-v8.h"
+#include "cogl-v8-color.h"
+
+static v8::Handle<v8::Value>
+pipelineSetColor (const v8::Arguments& args)
+{
+  if (args.Length () < 1)
+    return v8::Undefined();
+
+  v8::HandleScope scope;
+
+  v8::Handle<v8::Value> arg = args[0];
+  v8::String::AsciiValue value (arg);
+
+  CoglColor color;
+  if (_cogl_color_init_from_string (&color,
+                                    *value,
+                                    &_cogl_v8_context.colors_hash))
+    {
+      v8::Handle<v8::Object> holder = args.Holder();
+      CoglPipeline *pipeline =
+        static_cast<CoglPipeline *>(holder->GetPointerFromInternalField (0));
+
+      g_print ("setColor (%f, %f, %f, %f)\n",
+               cogl_color_get_red_float (&color),
+               cogl_color_get_green_float (&color),
+               cogl_color_get_blue_float (&color),
+               cogl_color_get_alpha_float (&color));
+
+      cogl_pipeline_set_color (pipeline, &color);
+    }
+  else
+    {
+      v8::ThrowException(v8::String::New ("Error parsing color"));
+      return v8::Undefined();
+    }
+
+  return v8::Undefined();
+}
+
+static v8::Handle<v8::Value>
+Pipeline (const v8::Arguments& args)
+{
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> _template = _cogl_v8_context.pipeline_template;
+  v8::Handle<v8::Object> _this = args.This();
+
+  /* This trick is to make the new operator optional for object
+   * constructor functions. The idea was borrowed from jQuery.
+   *
+   * XXX: for reference a similar trick can be done in javascript using:
+   * if (!(this instanceof arguments.callee))
+   *   return new cogl.Pipeline();
+   */
+  if (!(_template->HasInstance (_this)))
+    return _template->GetFunction ()->NewInstance ();
+
+  CoglPipeline *pipeline = cogl_pipeline_new (_cogl_v8_context.ctx);
+  _this->SetPointerInInternalField (0, pipeline);
+
+  v8::Persistent<v8::Object> pipeline_instance =
+    v8::Persistent<v8::Object>::New (_this);
+  pipeline_instance.MakeWeak (pipeline, _cogl_v8_object_weak_callback);
+
+  return v8::Undefined ();
+}
+
+extern "C" void
+_cogl_v8_pipeline_bind (v8::Handle<v8::ObjectTemplate> cogl)
+{
+  v8::HandleScope scope;
+
+  _cogl_v8_context.pipeline_template =
+    v8::Persistent<v8::FunctionTemplate>::New (v8::FunctionTemplate::New (Pipeline));
+
+  /* A signature seems to provide a good way of asking the v8 engine
+   * to do some automatic type checking of arguments and of 'this'
+   * when a method is called so we can be absolutely sure that our
+   * native methods only ever get called for objects *we* created
+   * where we know we own any internal fields set on those objects.
+   *
+   * Without this guarantee it would be possible for rouge code to
+   * copy the function objects for methods into other objects and
+   * potentially cause a crash if we were to try accessing internal
+   * fields that might not be available or might be owned by something
+   * else.
+   *
+   * Lots of digging through code and forums trying to figure out how
+   * to safely validate 'this' when a method is called eventually lead
+   * me to this forum topic which also details very important
+   * information about the Arguments::Holder() function, required if
+   * you want to write robust bindings...
+   *
+   * https://groups.google.com/forum/?fromgroups#!topic/v8-users/Axf4hF_RfZo
+   *
+   *  "In short: if you specify, through a Signature, that a function
+   *   must only be called on instances of function template T, the
+   *   value returned by Holder is guaranteed to hold an instance
+   *   created from T or another function template that directly or
+   *   indirectly "FunctionTemplate::Inherit"s from T.  No guarantees
+   *   hold about the type of This."
+   *
+   * It would be nice if the v8 documentation said more than just:
+   *
+   *   "A Signature specifies which receivers and arguments a function
+   *   can legally be called with."
+   *
+   * and said more than this about Arguments::Holder():
+   *
+   *   "Definition at line 3930 of file v8.h."
+   */
+  v8::Handle<v8::Signature> signature =
+    v8::Signature::New (_cogl_v8_context.pipeline_template);
+
+  v8::Local<v8::ObjectTemplate> instance_template =
+    _cogl_v8_context.pipeline_template->InstanceTemplate ();
+
+  v8::Handle<v8::FunctionTemplate> set_color_template =
+    v8::FunctionTemplate::New (pipelineSetColor,
+                               v8::Handle<v8::Value>(),
+                               signature);
+  instance_template->Set (v8::String::New ("setColor"), set_color_template);
+
+  instance_template->SetInternalFieldCount (1);
+  cogl->Set (v8::String::New ("Pipeline"), _cogl_v8_context.pipeline_template);
+}
diff --git a/bindings/v8/cogl-v8-pipeline.h b/bindings/v8/cogl-v8-pipeline.h
new file mode 100644
index 0000000..4f389b4
--- /dev/null
+++ b/bindings/v8/cogl-v8-pipeline.h
@@ -0,0 +1,33 @@
+/*
+ * Cogl V8 Bindings
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * 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 __COGL_V8_PIPELINE_H__
+#define __COGL_V8_PIPELINE_H__
+
+#include <v8.h>
+
+G_BEGIN_DECLS
+
+void
+_cogl_v8_pipeline_bind (v8::Handle<v8::ObjectTemplate> cogl);
+
+G_END_DECLS
+
+#endif /* __COGL_V8_PIPELINE_H__ */
diff --git a/bindings/v8/cogl-v8-primitive.cc b/bindings/v8/cogl-v8-primitive.cc
new file mode 100644
index 0000000..324564c
--- /dev/null
+++ b/bindings/v8/cogl-v8-primitive.cc
@@ -0,0 +1,116 @@
+/*
+ * Cogl V8 Bindings
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * 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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <v8.h>
+
+#include <cogl/cogl.h>
+
+#include "cogl-v8.h"
+
+#if 0
+static v8::Handle<v8::Value>
+primitiveSetColor (const v8::Arguments& args)
+{
+  if (args.Length () < 1) return v8::Undefined();
+  v8::HandleScope scope;
+  v8::Handle<v8::Value> arg = args[0];
+  v8::String::AsciiValue value (arg);
+
+  CoglColor color;
+  if (_cogl_color_init_from_string (&color,
+                                    *value,
+                                    &_cogl_v8_context.colors_hash))
+    {
+      v8::Handle<v8::Object> holder = args.Holder();
+      CoglPrimitive *primitive =
+        static_cast<CoglPrimitive *>(holder->GetPointerFromInternalField (0));
+
+      cogl_primitive_set_color (primitive, &color);
+    }
+  else
+    {
+      v8::ThrowException(v8::String::New ("Error parsing color"));
+      return v8::Undefined();
+    }
+
+  return v8::Undefined();
+}
+#endif
+
+static v8::Handle<v8::Value>
+Primitive (const v8::Arguments& args)
+{
+  v8::HandleScope scope;
+  v8::Handle<v8::FunctionTemplate> _template = _cogl_v8_context.primitive_template;
+  v8::Handle<v8::Object> _this = args.This();
+
+  if (!(_template->HasInstance (_this)))
+    return _template->GetFunction ()->NewInstance ();
+
+  CoglVertexP2C4 triangle_vertices[] = {
+        {0, 0.7, 0xff, 0x00, 0x00, 0x80},
+        {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff},
+        {0.7, -0.7, 0x00, 0x00, 0xff, 0xff}
+  };
+
+  CoglPrimitive *primitive =
+    cogl_primitive_new_p2c4 (_cogl_v8_context.ctx,
+                             COGL_VERTICES_MODE_TRIANGLES,
+                             3, triangle_vertices);
+  _this->SetPointerInInternalField (0, primitive);
+
+  v8::Persistent<v8::Object> primitive_instance =
+    v8::Persistent<v8::Object>::New (_this);
+  primitive_instance.MakeWeak (primitive, _cogl_v8_object_weak_callback);
+
+  return v8::Undefined ();
+}
+
+extern "C" void
+_cogl_v8_primitive_bind (v8::Handle<v8::ObjectTemplate> cogl)
+{
+  v8::HandleScope scope;
+
+  _cogl_v8_context.primitive_template =
+    v8::Persistent<v8::FunctionTemplate>::New (v8::FunctionTemplate::New (Primitive));
+
+  v8::Handle<v8::Signature> signature =
+    v8::Signature::New (_cogl_v8_context.primitive_template);
+
+  v8::Local<v8::ObjectTemplate> instance_template =
+    _cogl_v8_context.primitive_template->InstanceTemplate ();
+
+#if 0
+  v8::Handle<v8::FunctionTemplate> set_color_template =
+    v8::FunctionTemplate::New (primitiveSetColor,
+                               v8::Handle<v8::Value>(),
+                               signature);
+  instance_template->Set (v8::String::New ("setColor"), set_color_template);
+#endif
+
+  instance_template->SetInternalFieldCount (1);
+  cogl->Set (v8::String::New ("Primitive"), _cogl_v8_context.primitive_template);
+}
diff --git a/bindings/v8/cogl-v8-primitive.h b/bindings/v8/cogl-v8-primitive.h
new file mode 100644
index 0000000..741d73a
--- /dev/null
+++ b/bindings/v8/cogl-v8-primitive.h
@@ -0,0 +1,33 @@
+/*
+ * Cogl V8 Bindings
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * 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 __COGL_V8_PRIMITIVE_H__
+#define __COGL_V8_PRIMITIVE_H__
+
+#include <v8.h>
+
+G_BEGIN_DECLS
+
+void
+_cogl_v8_primitive_bind (v8::Handle<v8::ObjectTemplate> cogl);
+
+G_END_DECLS
+
+#endif /* __COGL_V8_PRIMITIVE_H__ */
diff --git a/bindings/v8/cogl-v8.cc b/bindings/v8/cogl-v8.cc
new file mode 100644
index 0000000..1973cbd
--- /dev/null
+++ b/bindings/v8/cogl-v8.cc
@@ -0,0 +1,193 @@
+/*
+ * Cogl V8 Bindings
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * 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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+
+#include <v8.h>
+
+#include <cogl/cogl.h>
+
+#include "cogl-v8.h"
+#include "cogl-v8-pipeline.h"
+#include "cogl-v8-primitive.h"
+
+CoglV8Context _cogl_v8_context;
+
+extern "C" void
+_cogl_v8_object_weak_callback (v8::Persistent<v8::Value> object, void *parameter)
+{
+  CoglObject *cogl_object = static_cast<CoglObject *>(parameter);
+
+  cogl_object_unref (cogl_object);
+
+  object.Dispose ();
+  object.Clear ();
+}
+
+static void
+cogl_v8_add_bindings (v8::Handle<v8::ObjectTemplate> global)
+{
+  v8::Handle<v8::ObjectTemplate> cogl = v8::ObjectTemplate::New ();
+  global->Set (v8::String::New ("cogl"), cogl);
+
+  _cogl_v8_pipeline_bind (cogl);
+  _cogl_v8_primitive_bind (cogl);
+}
+
+static v8::Handle<v8::Value>
+runMain (const v8::Arguments& args)
+{
+  g_main_loop_run (_cogl_v8_context.loop);
+  return v8::Undefined ();
+}
+
+static gboolean
+paint_cb (void *user_data)
+{
+  cogl_framebuffer_clear4f (_cogl_v8_context.fb,
+                            COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
+  cogl_framebuffer_draw_primitive (_cogl_v8_context.fb,
+                                   _cogl_v8_context.pipeline,
+                                   _cogl_v8_context.triangle);
+  cogl_onscreen_swap_buffers (COGL_ONSCREEN (_cogl_v8_context.fb));
+
+  /* If the driver can deliver swap complete events then we can remove
+   * the idle paint callback until we next get a swap complete event
+   * otherwise we keep the idle paint callback installed and simply
+   * paint as fast as the driver will allow... */
+  if (cogl_has_feature (_cogl_v8_context.ctx,
+                        COGL_FEATURE_ID_SWAP_BUFFERS_EVENT))
+    return FALSE; /* remove the callback */
+  else
+    return TRUE;
+}
+
+static void
+swap_complete_cb (CoglFramebuffer *framebuffer, void *user_data)
+{
+  g_idle_add (paint_cb, user_data);
+}
+
+static gboolean
+garbage_collect (void *user_data)
+{
+  v8::V8::IdleNotification ();
+  return TRUE;
+}
+
+int
+main (int argc, char **argv)
+{
+  CoglOnscreen *onscreen;
+  GError *error = NULL;
+  CoglVertexP2C4 triangle_vertices[] = {
+        {0, 0.7, 0xff, 0x00, 0x00, 0x80},
+        {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff},
+        {0.7, -0.7, 0x00, 0x00, 0xff, 0xff}
+  };
+  GSource *cogl_source;
+  char *script;
+  gsize len;
+
+  if (argc != 2)
+    {
+      g_printerr ("Usage: %s SCRIPT\n", argv[0]);
+      return 1;
+    }
+
+  _cogl_v8_context.ctx = cogl_context_new (NULL, &error);
+  if (!_cogl_v8_context.ctx)
+    {
+      g_error ("Failed to create context: %s\n", error->message);
+      return 1;
+    }
+
+  onscreen = cogl_onscreen_new (_cogl_v8_context.ctx, 640, 480);
+  cogl_onscreen_show (onscreen);
+  _cogl_v8_context.fb = COGL_FRAMEBUFFER (onscreen);
+
+  _cogl_v8_context.triangle =
+    cogl_primitive_new_p2c4 (_cogl_v8_context.ctx,
+                             COGL_VERTICES_MODE_TRIANGLES,
+                             3, triangle_vertices);
+  _cogl_v8_context.pipeline = cogl_pipeline_new (_cogl_v8_context.ctx);
+
+  v8::HandleScope handle_scope;
+
+  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New ();
+  global->Set (v8::String::New ("runMain"),
+               v8::FunctionTemplate::New (runMain));
+
+  cogl_v8_add_bindings (global);
+
+  _cogl_v8_context.v8_context = v8::Context::New (NULL, global);
+
+  v8::Context::Scope context_scope (_cogl_v8_context.v8_context);
+
+  if (!g_file_get_contents (argv[1], &script, &len, &error))
+    {
+      g_error ("Failed to read source: %s", error->message);
+      return 1;
+    }
+
+  v8::Handle<v8::String> source = v8::String::New (script, len);
+
+  v8::TryCatch trycatch;
+  _cogl_v8_context.script = v8::Script::Compile (source);
+  if (_cogl_v8_context.script.IsEmpty ())
+    {
+      v8::Handle<v8::Value> exception = trycatch.Exception ();
+      v8::String::AsciiValue exception_str (exception);
+      g_printerr ("Error compiling script: %s\n", *exception_str);
+      return 1;
+    }
+
+  cogl_source = cogl_glib_source_new (_cogl_v8_context.ctx, G_PRIORITY_DEFAULT);
+
+  g_source_attach (cogl_source, NULL);
+
+  if (cogl_has_feature (_cogl_v8_context.ctx,
+                        COGL_FEATURE_ID_SWAP_BUFFERS_EVENT))
+    cogl_onscreen_add_swap_buffers_callback (onscreen,
+                                             swap_complete_cb,
+                                             &_cogl_v8_context);
+
+  g_idle_add (paint_cb, &_cogl_v8_context);
+  g_idle_add (garbage_collect, NULL);
+
+  _cogl_v8_context.loop = g_main_loop_new (NULL, TRUE);
+
+  v8::Handle<v8::Value> v = _cogl_v8_context.script->Run ();
+  if (v.IsEmpty())
+    {
+      v8::Handle<v8::Value> exception = trycatch.Exception ();
+      v8::String::AsciiValue exception_str (exception);
+      g_printerr ("Error running script: %s\n", *exception_str);
+    }
+
+  _cogl_v8_context.v8_context.Dispose ();
+
+  return 0;
+}
diff --git a/bindings/v8/cogl-v8.h b/bindings/v8/cogl-v8.h
new file mode 100644
index 0000000..15d437e
--- /dev/null
+++ b/bindings/v8/cogl-v8.h
@@ -0,0 +1,57 @@
+/*
+ * Cogl V8 Bindings
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * 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 __COGL_V8_H__
+#define __COGL_V8_H__
+
+#include <glib.h>
+
+#include <v8.h>
+
+#include <cogl/cogl.h>
+
+typedef struct _CoglV8Context
+{
+  GHashTable *colors_hash;
+
+  CoglContext *ctx;
+  v8::Persistent<v8::Context> v8_context;
+  v8::Handle<v8::Script> script;
+
+  v8::Handle<v8::FunctionTemplate> pipeline_template;
+  v8::Handle<v8::FunctionTemplate> primitive_template;
+
+  CoglFramebuffer *fb;
+
+  CoglPrimitive *triangle;
+  CoglPipeline *pipeline;
+
+  GMainLoop *loop;
+} CoglV8Context;
+
+G_BEGIN_DECLS
+
+extern CoglV8Context _cogl_v8_context;
+
+void
+_cogl_v8_object_weak_callback (v8::Persistent<v8::Value> object, void *parameter);
+
+G_END_DECLS
+
+#endif /* __COGL_V8_H__ */
diff --git a/bindings/v8/color-table.h b/bindings/v8/color-table.h
new file mode 100644
index 0000000..679a26c
--- /dev/null
+++ b/bindings/v8/color-table.h
@@ -0,0 +1,1516 @@
+static const char *color_names[] =
+{
+  "alice blue",
+  "AliceBlue",
+  "antique white",
+  "AntiqueWhite",
+  "AntiqueWhite1",
+  "AntiqueWhite2",
+  "AntiqueWhite3",
+  "AntiqueWhite4",
+  "aquamarine",
+  "aquamarine1",
+  "aquamarine2",
+  "aquamarine3",
+  "aquamarine4",
+  "azure",
+  "azure1",
+  "azure2",
+  "azure3",
+  "azure4",
+  "beige",
+  "bisque",
+  "bisque1",
+  "bisque2",
+  "bisque3",
+  "bisque4",
+  "black",
+  "blanched almond",
+  "BlanchedAlmond",
+  "blue",
+  "blue violet",
+  "blue1",
+  "blue2",
+  "blue3",
+  "blue4",
+  "BlueViolet",
+  "brown",
+  "brown1",
+  "brown2",
+  "brown3",
+  "brown4",
+  "burlywood",
+  "burlywood1",
+  "burlywood2",
+  "burlywood3",
+  "burlywood4",
+  "cadet blue",
+  "CadetBlue",
+  "CadetBlue1",
+  "CadetBlue2",
+  "CadetBlue3",
+  "CadetBlue4",
+  "chartreuse",
+  "chartreuse1",
+  "chartreuse2",
+  "chartreuse3",
+  "chartreuse4",
+  "chocolate",
+  "chocolate1",
+  "chocolate2",
+  "chocolate3",
+  "chocolate4",
+  "coral",
+  "coral1",
+  "coral2",
+  "coral3",
+  "coral4",
+  "cornflower blue",
+  "CornflowerBlue",
+  "cornsilk",
+  "cornsilk1",
+  "cornsilk2",
+  "cornsilk3",
+  "cornsilk4",
+  "cyan",
+  "cyan1",
+  "cyan2",
+  "cyan3",
+  "cyan4",
+  "dark blue",
+  "dark cyan",
+  "dark goldenrod",
+  "dark gray",
+  "dark green",
+  "dark grey",
+  "dark khaki",
+  "dark magenta",
+  "dark olive green",
+  "dark orange",
+  "dark orchid",
+  "dark red",
+  "dark salmon",
+  "dark sea green",
+  "dark slate blue",
+  "dark slate gray",
+  "dark slate grey",
+  "dark turquoise",
+  "dark violet",
+  "DarkBlue",
+  "DarkCyan",
+  "DarkGoldenrod",
+  "DarkGoldenrod1",
+  "DarkGoldenrod2",
+  "DarkGoldenrod3",
+  "DarkGoldenrod4",
+  "DarkGray",
+  "DarkGreen",
+  "DarkGrey",
+  "DarkKhaki",
+  "DarkMagenta",
+  "DarkOliveGreen",
+  "DarkOliveGreen1",
+  "DarkOliveGreen2",
+  "DarkOliveGreen3",
+  "DarkOliveGreen4",
+  "DarkOrange",
+  "DarkOrange1",
+  "DarkOrange2",
+  "DarkOrange3",
+  "DarkOrange4",
+  "DarkOrchid",
+  "DarkOrchid1",
+  "DarkOrchid2",
+  "DarkOrchid3",
+  "DarkOrchid4",
+  "DarkRed",
+  "DarkSalmon",
+  "DarkSeaGreen",
+  "DarkSeaGreen1",
+  "DarkSeaGreen2",
+  "DarkSeaGreen3",
+  "DarkSeaGreen4",
+  "DarkSlateBlue",
+  "DarkSlateGray",
+  "DarkSlateGray1",
+  "DarkSlateGray2",
+  "DarkSlateGray3",
+  "DarkSlateGray4",
+  "DarkSlateGrey",
+  "DarkTurquoise",
+  "DarkViolet",
+  "deep pink",
+  "deep sky blue",
+  "DeepPink",
+  "DeepPink1",
+  "DeepPink2",
+  "DeepPink3",
+  "DeepPink4",
+  "DeepSkyBlue",
+  "DeepSkyBlue1",
+  "DeepSkyBlue2",
+  "DeepSkyBlue3",
+  "DeepSkyBlue4",
+  "dim gray",
+  "dim grey",
+  "DimGray",
+  "DimGrey",
+  "dodger blue",
+  "DodgerBlue",
+  "DodgerBlue1",
+  "DodgerBlue2",
+  "DodgerBlue3",
+  "DodgerBlue4",
+  "firebrick",
+  "firebrick1",
+  "firebrick2",
+  "firebrick3",
+  "firebrick4",
+  "floral white",
+  "FloralWhite",
+  "forest green",
+  "ForestGreen",
+  "gainsboro",
+  "ghost white",
+  "GhostWhite",
+  "gold",
+  "gold1",
+  "gold2",
+  "gold3",
+  "gold4",
+  "goldenrod",
+  "goldenrod1",
+  "goldenrod2",
+  "goldenrod3",
+  "goldenrod4",
+  "gray",
+  "gray0",
+  "gray1",
+  "gray10",
+  "gray100",
+  "gray11",
+  "gray12",
+  "gray13",
+  "gray14",
+  "gray15",
+  "gray16",
+  "gray17",
+  "gray18",
+  "gray19",
+  "gray2",
+  "gray20",
+  "gray21",
+  "gray22",
+  "gray23",
+  "gray24",
+  "gray25",
+  "gray26",
+  "gray27",
+  "gray28",
+  "gray29",
+  "gray3",
+  "gray30",
+  "gray31",
+  "gray32",
+  "gray33",
+  "gray34",
+  "gray35",
+  "gray36",
+  "gray37",
+  "gray38",
+  "gray39",
+  "gray4",
+  "gray40",
+  "gray41",
+  "gray42",
+  "gray43",
+  "gray44",
+  "gray45",
+  "gray46",
+  "gray47",
+  "gray48",
+  "gray49",
+  "gray5",
+  "gray50",
+  "gray51",
+  "gray52",
+  "gray53",
+  "gray54",
+  "gray55",
+  "gray56",
+  "gray57",
+  "gray58",
+  "gray59",
+  "gray6",
+  "gray60",
+  "gray61",
+  "gray62",
+  "gray63",
+  "gray64",
+  "gray65",
+  "gray66",
+  "gray67",
+  "gray68",
+  "gray69",
+  "gray7",
+  "gray70",
+  "gray71",
+  "gray72",
+  "gray73",
+  "gray74",
+  "gray75",
+  "gray76",
+  "gray77",
+  "gray78",
+  "gray79",
+  "gray8",
+  "gray80",
+  "gray81",
+  "gray82",
+  "gray83",
+  "gray84",
+  "gray85",
+  "gray86",
+  "gray87",
+  "gray88",
+  "gray89",
+  "gray9",
+  "gray90",
+  "gray91",
+  "gray92",
+  "gray93",
+  "gray94",
+  "gray95",
+  "gray96",
+  "gray97",
+  "gray98",
+  "gray99",
+  "green",
+  "green yellow",
+  "green1",
+  "green2",
+  "green3",
+  "green4",
+  "GreenYellow",
+  "grey",
+  "grey0",
+  "grey1",
+  "grey10",
+  "grey100",
+  "grey11",
+  "grey12",
+  "grey13",
+  "grey14",
+  "grey15",
+  "grey16",
+  "grey17",
+  "grey18",
+  "grey19",
+  "grey2",
+  "grey20",
+  "grey21",
+  "grey22",
+  "grey23",
+  "grey24",
+  "grey25",
+  "grey26",
+  "grey27",
+  "grey28",
+  "grey29",
+  "grey3",
+  "grey30",
+  "grey31",
+  "grey32",
+  "grey33",
+  "grey34",
+  "grey35",
+  "grey36",
+  "grey37",
+  "grey38",
+  "grey39",
+  "grey4",
+  "grey40",
+  "grey41",
+  "grey42",
+  "grey43",
+  "grey44",
+  "grey45",
+  "grey46",
+  "grey47",
+  "grey48",
+  "grey49",
+  "grey5",
+  "grey50",
+  "grey51",
+  "grey52",
+  "grey53",
+  "grey54",
+  "grey55",
+  "grey56",
+  "grey57",
+  "grey58",
+  "grey59",
+  "grey6",
+  "grey60",
+  "grey61",
+  "grey62",
+  "grey63",
+  "grey64",
+  "grey65",
+  "grey66",
+  "grey67",
+  "grey68",
+  "grey69",
+  "grey7",
+  "grey70",
+  "grey71",
+  "grey72",
+  "grey73",
+  "grey74",
+  "grey75",
+  "grey76",
+  "grey77",
+  "grey78",
+  "grey79",
+  "grey8",
+  "grey80",
+  "grey81",
+  "grey82",
+  "grey83",
+  "grey84",
+  "grey85",
+  "grey86",
+  "grey87",
+  "grey88",
+  "grey89",
+  "grey9",
+  "grey90",
+  "grey91",
+  "grey92",
+  "grey93",
+  "grey94",
+  "grey95",
+  "grey96",
+  "grey97",
+  "grey98",
+  "grey99",
+  "honeydew",
+  "honeydew1",
+  "honeydew2",
+  "honeydew3",
+  "honeydew4",
+  "hot pink",
+  "HotPink",
+  "HotPink1",
+  "HotPink2",
+  "HotPink3",
+  "HotPink4",
+  "indian red",
+  "IndianRed",
+  "IndianRed1",
+  "IndianRed2",
+  "IndianRed3",
+  "IndianRed4",
+  "ivory",
+  "ivory1",
+  "ivory2",
+  "ivory3",
+  "ivory4",
+  "khaki",
+  "khaki1",
+  "khaki2",
+  "khaki3",
+  "khaki4",
+  "lavender",
+  "lavender blush",
+  "LavenderBlush",
+  "LavenderBlush1",
+  "LavenderBlush2",
+  "LavenderBlush3",
+  "LavenderBlush4",
+  "lawn green",
+  "LawnGreen",
+  "lemon chiffon",
+  "LemonChiffon",
+  "LemonChiffon1",
+  "LemonChiffon2",
+  "LemonChiffon3",
+  "LemonChiffon4",
+  "light blue",
+  "light coral",
+  "light cyan",
+  "light goldenrod",
+  "light goldenrod yellow",
+  "light gray",
+  "light green",
+  "light grey",
+  "light pink",
+  "light salmon",
+  "light sea green",
+  "light sky blue",
+  "light slate blue",
+  "light slate gray",
+  "light slate grey",
+  "light steel blue",
+  "light yellow",
+  "LightBlue",
+  "LightBlue1",
+  "LightBlue2",
+  "LightBlue3",
+  "LightBlue4",
+  "LightCoral",
+  "LightCyan",
+  "LightCyan1",
+  "LightCyan2",
+  "LightCyan3",
+  "LightCyan4",
+  "LightGoldenrod",
+  "LightGoldenrod1",
+  "LightGoldenrod2",
+  "LightGoldenrod3",
+  "LightGoldenrod4",
+  "LightGoldenrodYellow",
+  "LightGray",
+  "LightGreen",
+  "LightGrey",
+  "LightPink",
+  "LightPink1",
+  "LightPink2",
+  "LightPink3",
+  "LightPink4",
+  "LightSalmon",
+  "LightSalmon1",
+  "LightSalmon2",
+  "LightSalmon3",
+  "LightSalmon4",
+  "LightSeaGreen",
+  "LightSkyBlue",
+  "LightSkyBlue1",
+  "LightSkyBlue2",
+  "LightSkyBlue3",
+  "LightSkyBlue4",
+  "LightSlateBlue",
+  "LightSlateGray",
+  "LightSlateGrey",
+  "LightSteelBlue",
+  "LightSteelBlue1",
+  "LightSteelBlue2",
+  "LightSteelBlue3",
+  "LightSteelBlue4",
+  "LightYellow",
+  "LightYellow1",
+  "LightYellow2",
+  "LightYellow3",
+  "LightYellow4",
+  "lime green",
+  "LimeGreen",
+  "linen",
+  "magenta",
+  "magenta1",
+  "magenta2",
+  "magenta3",
+  "magenta4",
+  "maroon",
+  "maroon1",
+  "maroon2",
+  "maroon3",
+  "maroon4",
+  "medium aquamarine",
+  "medium blue",
+  "medium orchid",
+  "medium purple",
+  "medium sea green",
+  "medium slate blue",
+  "medium spring green",
+  "medium turquoise",
+  "medium violet red",
+  "MediumAquamarine",
+  "MediumBlue",
+  "MediumOrchid",
+  "MediumOrchid1",
+  "MediumOrchid2",
+  "MediumOrchid3",
+  "MediumOrchid4",
+  "MediumPurple",
+  "MediumPurple1",
+  "MediumPurple2",
+  "MediumPurple3",
+  "MediumPurple4",
+  "MediumSeaGreen",
+  "MediumSlateBlue",
+  "MediumSpringGreen",
+  "MediumTurquoise",
+  "MediumVioletRed",
+  "midnight blue",
+  "MidnightBlue",
+  "mint cream",
+  "MintCream",
+  "misty rose",
+  "MistyRose",
+  "MistyRose1",
+  "MistyRose2",
+  "MistyRose3",
+  "MistyRose4",
+  "moccasin",
+  "navajo white",
+  "NavajoWhite",
+  "NavajoWhite1",
+  "NavajoWhite2",
+  "NavajoWhite3",
+  "NavajoWhite4",
+  "navy",
+  "navy blue",
+  "NavyBlue",
+  "old lace",
+  "OldLace",
+  "olive drab",
+  "OliveDrab",
+  "OliveDrab1",
+  "OliveDrab2",
+  "OliveDrab3",
+  "OliveDrab4",
+  "orange",
+  "orange red",
+  "orange1",
+  "orange2",
+  "orange3",
+  "orange4",
+  "OrangeRed",
+  "OrangeRed1",
+  "OrangeRed2",
+  "OrangeRed3",
+  "OrangeRed4",
+  "orchid",
+  "orchid1",
+  "orchid2",
+  "orchid3",
+  "orchid4",
+  "pale goldenrod",
+  "pale green",
+  "pale turquoise",
+  "pale violet red",
+  "PaleGoldenrod",
+  "PaleGreen",
+  "PaleGreen1",
+  "PaleGreen2",
+  "PaleGreen3",
+  "PaleGreen4",
+  "PaleTurquoise",
+  "PaleTurquoise1",
+  "PaleTurquoise2",
+  "PaleTurquoise3",
+  "PaleTurquoise4",
+  "PaleVioletRed",
+  "PaleVioletRed1",
+  "PaleVioletRed2",
+  "PaleVioletRed3",
+  "PaleVioletRed4",
+  "papaya whip",
+  "PapayaWhip",
+  "peach puff",
+  "PeachPuff",
+  "PeachPuff1",
+  "PeachPuff2",
+  "PeachPuff3",
+  "PeachPuff4",
+  "peru",
+  "pink",
+  "pink1",
+  "pink2",
+  "pink3",
+  "pink4",
+  "plum",
+  "plum1",
+  "plum2",
+  "plum3",
+  "plum4",
+  "powder blue",
+  "PowderBlue",
+  "purple",
+  "purple1",
+  "purple2",
+  "purple3",
+  "purple4",
+  "red",
+  "red1",
+  "red2",
+  "red3",
+  "red4",
+  "rosy brown",
+  "RosyBrown",
+  "RosyBrown1",
+  "RosyBrown2",
+  "RosyBrown3",
+  "RosyBrown4",
+  "royal blue",
+  "RoyalBlue",
+  "RoyalBlue1",
+  "RoyalBlue2",
+  "RoyalBlue3",
+  "RoyalBlue4",
+  "saddle brown",
+  "SaddleBrown",
+  "salmon",
+  "salmon1",
+  "salmon2",
+  "salmon3",
+  "salmon4",
+  "sandy brown",
+  "SandyBrown",
+  "sea green",
+  "SeaGreen",
+  "SeaGreen1",
+  "SeaGreen2",
+  "SeaGreen3",
+  "SeaGreen4",
+  "seashell",
+  "seashell1",
+  "seashell2",
+  "seashell3",
+  "seashell4",
+  "sienna",
+  "sienna1",
+  "sienna2",
+  "sienna3",
+  "sienna4",
+  "sky blue",
+  "SkyBlue",
+  "SkyBlue1",
+  "SkyBlue2",
+  "SkyBlue3",
+  "SkyBlue4",
+  "slate blue",
+  "slate gray",
+  "slate grey",
+  "SlateBlue",
+  "SlateBlue1",
+  "SlateBlue2",
+  "SlateBlue3",
+  "SlateBlue4",
+  "SlateGray",
+  "SlateGray1",
+  "SlateGray2",
+  "SlateGray3",
+  "SlateGray4",
+  "SlateGrey",
+  "snow",
+  "snow1",
+  "snow2",
+  "snow3",
+  "snow4",
+  "spring green",
+  "SpringGreen",
+  "SpringGreen1",
+  "SpringGreen2",
+  "SpringGreen3",
+  "SpringGreen4",
+  "steel blue",
+  "SteelBlue",
+  "SteelBlue1",
+  "SteelBlue2",
+  "SteelBlue3",
+  "SteelBlue4",
+  "tan",
+  "tan1",
+  "tan2",
+  "tan3",
+  "tan4",
+  "thistle",
+  "thistle1",
+  "thistle2",
+  "thistle3",
+  "thistle4",
+  "tomato",
+  "tomato1",
+  "tomato2",
+  "tomato3",
+  "tomato4",
+  "turquoise",
+  "turquoise1",
+  "turquoise2",
+  "turquoise3",
+  "turquoise4",
+  "violet",
+  "violet red",
+  "VioletRed",
+  "VioletRed1",
+  "VioletRed2",
+  "VioletRed3",
+  "VioletRed4",
+  "wheat",
+  "wheat1",
+  "wheat2",
+  "wheat3",
+  "wheat4",
+  "white",
+  "white smoke",
+  "WhiteSmoke",
+  "yellow",
+  "yellow green",
+  "yellow1",
+  "yellow2",
+  "yellow3",
+  "yellow4",
+  "YellowGreen"
+};
+
+typedef struct {
+    unsigned char red;
+    unsigned char green;
+    unsigned char blue;
+} ColorEntry;
+
+static const ColorEntry color_entries[] = {
+  { 240, 248, 255 },
+  { 240, 248, 255 },
+  { 250, 235, 215 },
+  { 250, 235, 215 },
+  { 255, 239, 219 },
+  { 238, 223, 204 },
+  { 205, 192, 176 },
+  { 139, 131, 120 },
+  { 127, 255, 212 },
+  { 127, 255, 212 },
+  { 118, 238, 198 },
+  { 102, 205, 170 },
+  { 69, 139, 116 },
+  { 240, 255, 255 },
+  { 240, 255, 255 },
+  { 224, 238, 238 },
+  { 193, 205, 205 },
+  { 131, 139, 139 },
+  { 245, 245, 220 },
+  { 255, 228, 196 },
+  { 255, 228, 196 },
+  { 238, 213, 183 },
+  { 205, 183, 158 },
+  { 139, 125, 107 },
+  { 0, 0, 0 },
+  { 255, 235, 205 },
+  { 255, 235, 205 },
+  { 0, 0, 255 },
+  { 138, 43, 226 },
+  { 0, 0, 255 },
+  { 0, 0, 238 },
+  { 0, 0, 205 },
+  { 0, 0, 139 },
+  { 138, 43, 226 },
+  { 165, 42, 42 },
+  { 255, 64, 64 },
+  { 238, 59, 59 },
+  { 205, 51, 51 },
+  { 139, 35, 35 },
+  { 222, 184, 135 },
+  { 255, 211, 155 },
+  { 238, 197, 145 },
+  { 205, 170, 125 },
+  { 139, 115, 85 },
+  { 95, 158, 160 },
+  { 95, 158, 160 },
+  { 152, 245, 255 },
+  { 142, 229, 238 },
+  { 122, 197, 205 },
+  { 83, 134, 139 },
+  { 127, 255, 0 },
+  { 127, 255, 0 },
+  { 118, 238, 0 },
+  { 102, 205, 0 },
+  { 69, 139, 0 },
+  { 210, 105, 30 },
+  { 255, 127, 36 },
+  { 238, 118, 33 },
+  { 205, 102, 29 },
+  { 139, 69, 19 },
+  { 255, 127, 80 },
+  { 255, 114, 86 },
+  { 238, 106, 80 },
+  { 205, 91, 69 },
+  { 139, 62, 47 },
+  { 100, 149, 237 },
+  { 100, 149, 237 },
+  { 255, 248, 220 },
+  { 255, 248, 220 },
+  { 238, 232, 205 },
+  { 205, 200, 177 },
+  { 139, 136, 120 },
+  { 0, 255, 255 },
+  { 0, 255, 255 },
+  { 0, 238, 238 },
+  { 0, 205, 205 },
+  { 0, 139, 139 },
+  { 0, 0, 139 },
+  { 0, 139, 139 },
+  { 184, 134, 11 },
+  { 169, 169, 169 },
+  { 0, 100, 0 },
+  { 169, 169, 169 },
+  { 189, 183, 107 },
+  { 139, 0, 139 },
+  { 85, 107, 47 },
+  { 255, 140, 0 },
+  { 153, 50, 204 },
+  { 139, 0, 0 },
+  { 233, 150, 122 },
+  { 143, 188, 143 },
+  { 72, 61, 139 },
+  { 47, 79, 79 },
+  { 47, 79, 79 },
+  { 0, 206, 209 },
+  { 148, 0, 211 },
+  { 0, 0, 139 },
+  { 0, 139, 139 },
+  { 184, 134, 11 },
+  { 255, 185, 15 },
+  { 238, 173, 14 },
+  { 205, 149, 12 },
+  { 139, 101, 8 },
+  { 169, 169, 169 },
+  { 0, 100, 0 },
+  { 169, 169, 169 },
+  { 189, 183, 107 },
+  { 139, 0, 139 },
+  { 85, 107, 47 },
+  { 202, 255, 112 },
+  { 188, 238, 104 },
+  { 162, 205, 90 },
+  { 110, 139, 61 },
+  { 255, 140, 0 },
+  { 255, 127, 0 },
+  { 238, 118, 0 },
+  { 205, 102, 0 },
+  { 139, 69, 0 },
+  { 153, 50, 204 },
+  { 191, 62, 255 },
+  { 178, 58, 238 },
+  { 154, 50, 205 },
+  { 104, 34, 139 },
+  { 139, 0, 0 },
+  { 233, 150, 122 },
+  { 143, 188, 143 },
+  { 193, 255, 193 },
+  { 180, 238, 180 },
+  { 155, 205, 155 },
+  { 105, 139, 105 },
+  { 72, 61, 139 },
+  { 47, 79, 79 },
+  { 151, 255, 255 },
+  { 141, 238, 238 },
+  { 121, 205, 205 },
+  { 82, 139, 139 },
+  { 47, 79, 79 },
+  { 0, 206, 209 },
+  { 148, 0, 211 },
+  { 255, 20, 147 },
+  { 0, 191, 255 },
+  { 255, 20, 147 },
+  { 255, 20, 147 },
+  { 238, 18, 137 },
+  { 205, 16, 118 },
+  { 139, 10, 80 },
+  { 0, 191, 255 },
+  { 0, 191, 255 },
+  { 0, 178, 238 },
+  { 0, 154, 205 },
+  { 0, 104, 139 },
+  { 105, 105, 105 },
+  { 105, 105, 105 },
+  { 105, 105, 105 },
+  { 105, 105, 105 },
+  { 30, 144, 255 },
+  { 30, 144, 255 },
+  { 30, 144, 255 },
+  { 28, 134, 238 },
+  { 24, 116, 205 },
+  { 16, 78, 139 },
+  { 178, 34, 34 },
+  { 255, 48, 48 },
+  { 238, 44, 44 },
+  { 205, 38, 38 },
+  { 139, 26, 26 },
+  { 255, 250, 240 },
+  { 255, 250, 240 },
+  { 34, 139, 34 },
+  { 34, 139, 34 },
+  { 220, 220, 220 },
+  { 248, 248, 255 },
+  { 248, 248, 255 },
+  { 255, 215, 0 },
+  { 255, 215, 0 },
+  { 238, 201, 0 },
+  { 205, 173, 0 },
+  { 139, 117, 0 },
+  { 218, 165, 32 },
+  { 255, 193, 37 },
+  { 238, 180, 34 },
+  { 205, 155, 29 },
+  { 139, 105, 20 },
+  { 190, 190, 190 },
+  { 0, 0, 0 },
+  { 3, 3, 3 },
+  { 26, 26, 26 },
+  { 255, 255, 255 },
+  { 28, 28, 28 },
+  { 31, 31, 31 },
+  { 33, 33, 33 },
+  { 36, 36, 36 },
+  { 38, 38, 38 },
+  { 41, 41, 41 },
+  { 43, 43, 43 },
+  { 46, 46, 46 },
+  { 48, 48, 48 },
+  { 5, 5, 5 },
+  { 51, 51, 51 },
+  { 54, 54, 54 },
+  { 56, 56, 56 },
+  { 59, 59, 59 },
+  { 61, 61, 61 },
+  { 64, 64, 64 },
+  { 66, 66, 66 },
+  { 69, 69, 69 },
+  { 71, 71, 71 },
+  { 74, 74, 74 },
+  { 8, 8, 8 },
+  { 77, 77, 77 },
+  { 79, 79, 79 },
+  { 82, 82, 82 },
+  { 84, 84, 84 },
+  { 87, 87, 87 },
+  { 89, 89, 89 },
+  { 92, 92, 92 },
+  { 94, 94, 94 },
+  { 97, 97, 97 },
+  { 99, 99, 99 },
+  { 10, 10, 10 },
+  { 102, 102, 102 },
+  { 105, 105, 105 },
+  { 107, 107, 107 },
+  { 110, 110, 110 },
+  { 112, 112, 112 },
+  { 115, 115, 115 },
+  { 117, 117, 117 },
+  { 120, 120, 120 },
+  { 122, 122, 122 },
+  { 125, 125, 125 },
+  { 13, 13, 13 },
+  { 127, 127, 127 },
+  { 130, 130, 130 },
+  { 133, 133, 133 },
+  { 135, 135, 135 },
+  { 138, 138, 138 },
+  { 140, 140, 140 },
+  { 143, 143, 143 },
+  { 145, 145, 145 },
+  { 148, 148, 148 },
+  { 150, 150, 150 },
+  { 15, 15, 15 },
+  { 153, 153, 153 },
+  { 156, 156, 156 },
+  { 158, 158, 158 },
+  { 161, 161, 161 },
+  { 163, 163, 163 },
+  { 166, 166, 166 },
+  { 168, 168, 168 },
+  { 171, 171, 171 },
+  { 173, 173, 173 },
+  { 176, 176, 176 },
+  { 18, 18, 18 },
+  { 179, 179, 179 },
+  { 181, 181, 181 },
+  { 184, 184, 184 },
+  { 186, 186, 186 },
+  { 189, 189, 189 },
+  { 191, 191, 191 },
+  { 194, 194, 194 },
+  { 196, 196, 196 },
+  { 199, 199, 199 },
+  { 201, 201, 201 },
+  { 20, 20, 20 },
+  { 204, 204, 204 },
+  { 207, 207, 207 },
+  { 209, 209, 209 },
+  { 212, 212, 212 },
+  { 214, 214, 214 },
+  { 217, 217, 217 },
+  { 219, 219, 219 },
+  { 222, 222, 222 },
+  { 224, 224, 224 },
+  { 227, 227, 227 },
+  { 23, 23, 23 },
+  { 229, 229, 229 },
+  { 232, 232, 232 },
+  { 235, 235, 235 },
+  { 237, 237, 237 },
+  { 240, 240, 240 },
+  { 242, 242, 242 },
+  { 245, 245, 245 },
+  { 247, 247, 247 },
+  { 250, 250, 250 },
+  { 252, 252, 252 },
+  { 0, 255, 0 },
+  { 173, 255, 47 },
+  { 0, 255, 0 },
+  { 0, 238, 0 },
+  { 0, 205, 0 },
+  { 0, 139, 0 },
+  { 173, 255, 47 },
+  { 190, 190, 190 },
+  { 0, 0, 0 },
+  { 3, 3, 3 },
+  { 26, 26, 26 },
+  { 255, 255, 255 },
+  { 28, 28, 28 },
+  { 31, 31, 31 },
+  { 33, 33, 33 },
+  { 36, 36, 36 },
+  { 38, 38, 38 },
+  { 41, 41, 41 },
+  { 43, 43, 43 },
+  { 46, 46, 46 },
+  { 48, 48, 48 },
+  { 5, 5, 5 },
+  { 51, 51, 51 },
+  { 54, 54, 54 },
+  { 56, 56, 56 },
+  { 59, 59, 59 },
+  { 61, 61, 61 },
+  { 64, 64, 64 },
+  { 66, 66, 66 },
+  { 69, 69, 69 },
+  { 71, 71, 71 },
+  { 74, 74, 74 },
+  { 8, 8, 8 },
+  { 77, 77, 77 },
+  { 79, 79, 79 },
+  { 82, 82, 82 },
+  { 84, 84, 84 },
+  { 87, 87, 87 },
+  { 89, 89, 89 },
+  { 92, 92, 92 },
+  { 94, 94, 94 },
+  { 97, 97, 97 },
+  { 99, 99, 99 },
+  { 10, 10, 10 },
+  { 102, 102, 102 },
+  { 105, 105, 105 },
+  { 107, 107, 107 },
+  { 110, 110, 110 },
+  { 112, 112, 112 },
+  { 115, 115, 115 },
+  { 117, 117, 117 },
+  { 120, 120, 120 },
+  { 122, 122, 122 },
+  { 125, 125, 125 },
+  { 13, 13, 13 },
+  { 127, 127, 127 },
+  { 130, 130, 130 },
+  { 133, 133, 133 },
+  { 135, 135, 135 },
+  { 138, 138, 138 },
+  { 140, 140, 140 },
+  { 143, 143, 143 },
+  { 145, 145, 145 },
+  { 148, 148, 148 },
+  { 150, 150, 150 },
+  { 15, 15, 15 },
+  { 153, 153, 153 },
+  { 156, 156, 156 },
+  { 158, 158, 158 },
+  { 161, 161, 161 },
+  { 163, 163, 163 },
+  { 166, 166, 166 },
+  { 168, 168, 168 },
+  { 171, 171, 171 },
+  { 173, 173, 173 },
+  { 176, 176, 176 },
+  { 18, 18, 18 },
+  { 179, 179, 179 },
+  { 181, 181, 181 },
+  { 184, 184, 184 },
+  { 186, 186, 186 },
+  { 189, 189, 189 },
+  { 191, 191, 191 },
+  { 194, 194, 194 },
+  { 196, 196, 196 },
+  { 199, 199, 199 },
+  { 201, 201, 201 },
+  { 20, 20, 20 },
+  { 204, 204, 204 },
+  { 207, 207, 207 },
+  { 209, 209, 209 },
+  { 212, 212, 212 },
+  { 214, 214, 214 },
+  { 217, 217, 217 },
+  { 219, 219, 219 },
+  { 222, 222, 222 },
+  { 224, 224, 224 },
+  { 227, 227, 227 },
+  { 23, 23, 23 },
+  { 229, 229, 229 },
+  { 232, 232, 232 },
+  { 235, 235, 235 },
+  { 237, 237, 237 },
+  { 240, 240, 240 },
+  { 242, 242, 242 },
+  { 245, 245, 245 },
+  { 247, 247, 247 },
+  { 250, 250, 250 },
+  { 252, 252, 252 },
+  { 240, 255, 240 },
+  { 240, 255, 240 },
+  { 224, 238, 224 },
+  { 193, 205, 193 },
+  { 131, 139, 131 },
+  { 255, 105, 180 },
+  { 255, 105, 180 },
+  { 255, 110, 180 },
+  { 238, 106, 167 },
+  { 205, 96, 144 },
+  { 139, 58, 98 },
+  { 205, 92, 92 },
+  { 205, 92, 92 },
+  { 255, 106, 106 },
+  { 238, 99, 99 },
+  { 205, 85, 85 },
+  { 139, 58, 58 },
+  { 255, 255, 240 },
+  { 255, 255, 240 },
+  { 238, 238, 224 },
+  { 205, 205, 193 },
+  { 139, 139, 131 },
+  { 240, 230, 140 },
+  { 255, 246, 143 },
+  { 238, 230, 133 },
+  { 205, 198, 115 },
+  { 139, 134, 78 },
+  { 230, 230, 250 },
+  { 255, 240, 245 },
+  { 255, 240, 245 },
+  { 255, 240, 245 },
+  { 238, 224, 229 },
+  { 205, 193, 197 },
+  { 139, 131, 134 },
+  { 124, 252, 0 },
+  { 124, 252, 0 },
+  { 255, 250, 205 },
+  { 255, 250, 205 },
+  { 255, 250, 205 },
+  { 238, 233, 191 },
+  { 205, 201, 165 },
+  { 139, 137, 112 },
+  { 173, 216, 230 },
+  { 240, 128, 128 },
+  { 224, 255, 255 },
+  { 238, 221, 130 },
+  { 250, 250, 210 },
+  { 211, 211, 211 },
+  { 144, 238, 144 },
+  { 211, 211, 211 },
+  { 255, 182, 193 },
+  { 255, 160, 122 },
+  { 32, 178, 170 },
+  { 135, 206, 250 },
+  { 132, 112, 255 },
+  { 119, 136, 153 },
+  { 119, 136, 153 },
+  { 176, 196, 222 },
+  { 255, 255, 224 },
+  { 173, 216, 230 },
+  { 191, 239, 255 },
+  { 178, 223, 238 },
+  { 154, 192, 205 },
+  { 104, 131, 139 },
+  { 240, 128, 128 },
+  { 224, 255, 255 },
+  { 224, 255, 255 },
+  { 209, 238, 238 },
+  { 180, 205, 205 },
+  { 122, 139, 139 },
+  { 238, 221, 130 },
+  { 255, 236, 139 },
+  { 238, 220, 130 },
+  { 205, 190, 112 },
+  { 139, 129, 76 },
+  { 250, 250, 210 },
+  { 211, 211, 211 },
+  { 144, 238, 144 },
+  { 211, 211, 211 },
+  { 255, 182, 193 },
+  { 255, 174, 185 },
+  { 238, 162, 173 },
+  { 205, 140, 149 },
+  { 139, 95, 101 },
+  { 255, 160, 122 },
+  { 255, 160, 122 },
+  { 238, 149, 114 },
+  { 205, 129, 98 },
+  { 139, 87, 66 },
+  { 32, 178, 170 },
+  { 135, 206, 250 },
+  { 176, 226, 255 },
+  { 164, 211, 238 },
+  { 141, 182, 205 },
+  { 96, 123, 139 },
+  { 132, 112, 255 },
+  { 119, 136, 153 },
+  { 119, 136, 153 },
+  { 176, 196, 222 },
+  { 202, 225, 255 },
+  { 188, 210, 238 },
+  { 162, 181, 205 },
+  { 110, 123, 139 },
+  { 255, 255, 224 },
+  { 255, 255, 224 },
+  { 238, 238, 209 },
+  { 205, 205, 180 },
+  { 139, 139, 122 },
+  { 50, 205, 50 },
+  { 50, 205, 50 },
+  { 250, 240, 230 },
+  { 255, 0, 255 },
+  { 255, 0, 255 },
+  { 238, 0, 238 },
+  { 205, 0, 205 },
+  { 139, 0, 139 },
+  { 176, 48, 96 },
+  { 255, 52, 179 },
+  { 238, 48, 167 },
+  { 205, 41, 144 },
+  { 139, 28, 98 },
+  { 102, 205, 170 },
+  { 0, 0, 205 },
+  { 186, 85, 211 },
+  { 147, 112, 219 },
+  { 60, 179, 113 },
+  { 123, 104, 238 },
+  { 0, 250, 154 },
+  { 72, 209, 204 },
+  { 199, 21, 133 },
+  { 102, 205, 170 },
+  { 0, 0, 205 },
+  { 186, 85, 211 },
+  { 224, 102, 255 },
+  { 209, 95, 238 },
+  { 180, 82, 205 },
+  { 122, 55, 139 },
+  { 147, 112, 219 },
+  { 171, 130, 255 },
+  { 159, 121, 238 },
+  { 137, 104, 205 },
+  { 93, 71, 139 },
+  { 60, 179, 113 },
+  { 123, 104, 238 },
+  { 0, 250, 154 },
+  { 72, 209, 204 },
+  { 199, 21, 133 },
+  { 25, 25, 112 },
+  { 25, 25, 112 },
+  { 245, 255, 250 },
+  { 245, 255, 250 },
+  { 255, 228, 225 },
+  { 255, 228, 225 },
+  { 255, 228, 225 },
+  { 238, 213, 210 },
+  { 205, 183, 181 },
+  { 139, 125, 123 },
+  { 255, 228, 181 },
+  { 255, 222, 173 },
+  { 255, 222, 173 },
+  { 255, 222, 173 },
+  { 238, 207, 161 },
+  { 205, 179, 139 },
+  { 139, 121, 94 },
+  { 0, 0, 128 },
+  { 0, 0, 128 },
+  { 0, 0, 128 },
+  { 253, 245, 230 },
+  { 253, 245, 230 },
+  { 107, 142, 35 },
+  { 107, 142, 35 },
+  { 192, 255, 62 },
+  { 179, 238, 58 },
+  { 154, 205, 50 },
+  { 105, 139, 34 },
+  { 255, 165, 0 },
+  { 255, 69, 0 },
+  { 255, 165, 0 },
+  { 238, 154, 0 },
+  { 205, 133, 0 },
+  { 139, 90, 0 },
+  { 255, 69, 0 },
+  { 255, 69, 0 },
+  { 238, 64, 0 },
+  { 205, 55, 0 },
+  { 139, 37, 0 },
+  { 218, 112, 214 },
+  { 255, 131, 250 },
+  { 238, 122, 233 },
+  { 205, 105, 201 },
+  { 139, 71, 137 },
+  { 238, 232, 170 },
+  { 152, 251, 152 },
+  { 175, 238, 238 },
+  { 219, 112, 147 },
+  { 238, 232, 170 },
+  { 152, 251, 152 },
+  { 154, 255, 154 },
+  { 144, 238, 144 },
+  { 124, 205, 124 },
+  { 84, 139, 84 },
+  { 175, 238, 238 },
+  { 187, 255, 255 },
+  { 174, 238, 238 },
+  { 150, 205, 205 },
+  { 102, 139, 139 },
+  { 219, 112, 147 },
+  { 255, 130, 171 },
+  { 238, 121, 159 },
+  { 205, 104, 137 },
+  { 139, 71, 93 },
+  { 255, 239, 213 },
+  { 255, 239, 213 },
+  { 255, 218, 185 },
+  { 255, 218, 185 },
+  { 255, 218, 185 },
+  { 238, 203, 173 },
+  { 205, 175, 149 },
+  { 139, 119, 101 },
+  { 205, 133, 63 },
+  { 255, 192, 203 },
+  { 255, 181, 197 },
+  { 238, 169, 184 },
+  { 205, 145, 158 },
+  { 139, 99, 108 },
+  { 221, 160, 221 },
+  { 255, 187, 255 },
+  { 238, 174, 238 },
+  { 205, 150, 205 },
+  { 139, 102, 139 },
+  { 176, 224, 230 },
+  { 176, 224, 230 },
+  { 160, 32, 240 },
+  { 155, 48, 255 },
+  { 145, 44, 238 },
+  { 125, 38, 205 },
+  { 85, 26, 139 },
+  { 255, 0, 0 },
+  { 255, 0, 0 },
+  { 238, 0, 0 },
+  { 205, 0, 0 },
+  { 139, 0, 0 },
+  { 188, 143, 143 },
+  { 188, 143, 143 },
+  { 255, 193, 193 },
+  { 238, 180, 180 },
+  { 205, 155, 155 },
+  { 139, 105, 105 },
+  { 65, 105, 225 },
+  { 65, 105, 225 },
+  { 72, 118, 255 },
+  { 67, 110, 238 },
+  { 58, 95, 205 },
+  { 39, 64, 139 },
+  { 139, 69, 19 },
+  { 139, 69, 19 },
+  { 250, 128, 114 },
+  { 255, 140, 105 },
+  { 238, 130, 98 },
+  { 205, 112, 84 },
+  { 139, 76, 57 },
+  { 244, 164, 96 },
+  { 244, 164, 96 },
+  { 46, 139, 87 },
+  { 46, 139, 87 },
+  { 84, 255, 159 },
+  { 78, 238, 148 },
+  { 67, 205, 128 },
+  { 46, 139, 87 },
+  { 255, 245, 238 },
+  { 255, 245, 238 },
+  { 238, 229, 222 },
+  { 205, 197, 191 },
+  { 139, 134, 130 },
+  { 160, 82, 45 },
+  { 255, 130, 71 },
+  { 238, 121, 66 },
+  { 205, 104, 57 },
+  { 139, 71, 38 },
+  { 135, 206, 235 },
+  { 135, 206, 235 },
+  { 135, 206, 255 },
+  { 126, 192, 238 },
+  { 108, 166, 205 },
+  { 74, 112, 139 },
+  { 106, 90, 205 },
+  { 112, 128, 144 },
+  { 112, 128, 144 },
+  { 106, 90, 205 },
+  { 131, 111, 255 },
+  { 122, 103, 238 },
+  { 105, 89, 205 },
+  { 71, 60, 139 },
+  { 112, 128, 144 },
+  { 198, 226, 255 },
+  { 185, 211, 238 },
+  { 159, 182, 205 },
+  { 108, 123, 139 },
+  { 112, 128, 144 },
+  { 255, 250, 250 },
+  { 255, 250, 250 },
+  { 238, 233, 233 },
+  { 205, 201, 201 },
+  { 139, 137, 137 },
+  { 0, 255, 127 },
+  { 0, 255, 127 },
+  { 0, 255, 127 },
+  { 0, 238, 118 },
+  { 0, 205, 102 },
+  { 0, 139, 69 },
+  { 70, 130, 180 },
+  { 70, 130, 180 },
+  { 99, 184, 255 },
+  { 92, 172, 238 },
+  { 79, 148, 205 },
+  { 54, 100, 139 },
+  { 210, 180, 140 },
+  { 255, 165, 79 },
+  { 238, 154, 73 },
+  { 205, 133, 63 },
+  { 139, 90, 43 },
+  { 216, 191, 216 },
+  { 255, 225, 255 },
+  { 238, 210, 238 },
+  { 205, 181, 205 },
+  { 139, 123, 139 },
+  { 255, 99, 71 },
+  { 255, 99, 71 },
+  { 238, 92, 66 },
+  { 205, 79, 57 },
+  { 139, 54, 38 },
+  { 64, 224, 208 },
+  { 0, 245, 255 },
+  { 0, 229, 238 },
+  { 0, 197, 205 },
+  { 0, 134, 139 },
+  { 238, 130, 238 },
+  { 208, 32, 144 },
+  { 208, 32, 144 },
+  { 255, 62, 150 },
+  { 238, 58, 140 },
+  { 205, 50, 120 },
+  { 139, 34, 82 },
+  { 245, 222, 179 },
+  { 255, 231, 186 },
+  { 238, 216, 174 },
+  { 205, 186, 150 },
+  { 139, 126, 102 },
+  { 255, 255, 255 },
+  { 245, 245, 245 },
+  { 245, 245, 245 },
+  { 255, 255, 0 },
+  { 154, 205, 50 },
+  { 255, 255, 0 },
+  { 238, 238, 0 },
+  { 205, 205, 0 },
+  { 139, 139, 0 },
+  { 154, 205, 50 }
+};
diff --git a/bindings/v8/test.js b/bindings/v8/test.js
new file mode 100644
index 0000000..3f074b0
--- /dev/null
+++ b/bindings/v8/test.js
@@ -0,0 +1,15 @@
+
+var primitive = cogl.Primitive();
+
+var pipeline = cogl.Pipeline();
+pipeline.setColor ("rgba(1, 1, 0, 1)");
+
+/*
+paint = function () {
+
+    onscreen.draw_primitive (primitive);
+}
+*/
+
+runMain();
+
diff --git a/build/autotools/v8.m4 b/build/autotools/v8.m4
new file mode 100644
index 0000000..0edf9ed
--- /dev/null
+++ b/build/autotools/v8.m4
@@ -0,0 +1,142 @@
+# SYNOPSIS
+#
+#   AX_LIB_V8([MINIMUM-VERSION])
+#
+# DESCRIPTION
+#
+#   Test for the V8 library from Google for embedding Javascript into C++ programs.
+#
+#   If no path to the installed boost library is given the macro searchs
+#   under /usr, /usr/local and /opt.
+#
+#   This macro calls:
+#
+#     AC_SUBST(V8_CPPFLAGS) / AC_SUBST(V8_LDFLAGS)
+#
+#   And sets:
+#
+#     HAVE_V8
+#
+# LICENSE
+#
+#   Copyright (c) 2009 Graham Cox <graham grahamcox co uk>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved.
+
+AC_DEFUN([AX_LIB_V8],
+[
+    AC_ARG_WITH([v8],
+        AC_HELP_STRING(
+            [--with-v8=@<:@ARG@:>@],
+            [use V8 library @<:@default=yes@:>@, optionally specify the prefix for v8 library]
+        ),
+        [
+        if test "$withval" = "no"; then
+            WANT_V8="no"
+        elif test "$withval" = "yes"; then
+            WANT_V8="yes"
+            ac_v8_path=""
+        else
+            WANT_V8="yes"
+            ac_v8_path="$withval"
+        fi
+        ],
+        [WANT_V8="yes"]
+    )
+
+    V8_CPPFLAGS=""
+    V8_LDFLAGS=""
+
+    if test "x$WANT_V8" = "xyes"; then
+
+        ac_v8_header="v8.h"
+
+        v8_version_req=ifelse([$1], [], [2.0.5.2], [$1])
+        v8_version_req_shorten=`expr $v8_version_req : '\([[0-9]]*\.[[0-9]]*\)'`
+        v8_version_req_major=`expr $v8_version_req : '\([[0-9]]*\)'`
+        v8_version_req_minor=`expr $v8_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
+        v8_version_req_micro=`expr $v8_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+        v8_version_req_nano=`expr $v8_version_req : '[[0-9]]*\.[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+        if test "x$v8_version_req_nano" = "x" ; then
+            v8_version_req_nano="0"
+        fi
+
+        v8_version_req_number=`expr $v8_version_req_major \* 1000000000 \
+                                   \+ $v8_version_req_minor \* 1000000 \
+                                   \+ $v8_version_req_micro \* 1000 \
+                                   \+ $v8_version_req_nano`
+
+        AC_MSG_CHECKING([for V8 library >= $v8_version_req])
+
+        if test "$ac_v8_path" != ""; then
+            ac_v8_ldflags="-L$ac_v8_path/lib"
+            ac_v8_cppflags="-I$ac_v8_path/include"
+        else
+            for ac_v8_path_tmp in /usr /usr/local /opt ; do
+                if test -f "$ac_v8_path_tmp/include/$ac_v8_header" \
+                    && test -r "$ac_v8_path_tmp/include/$ac_v8_header"; then
+                    ac_v8_path=$ac_v8_path_tmp
+                    ac_v8_cppflags="-I$ac_v8_path_tmp/include"
+                    ac_v8_ldflags="-L$ac_v8_path_tmp/lib"
+                    break;
+                fi
+            done
+        fi
+
+        ac_v8_ldflags="$ac_v8_ldflags -lv8"
+
+        saved_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="$CPPFLAGS $ac_v8_cppflags"
+
+        saved_LDFLAGS="$LDFLAGS"
+        LDFLAGS="$LDFLAGS $ac_v8_ldflags"
+
+        AC_LANG_PUSH([C++])
+        AC_TRY_COMPILE([#include <v8.h>], ,
+            success=yes, success=no)
+        if test "$success" = "yes"; then
+            AC_TRY_LINK([#include <v8.h>], 
+                [v8::V8::GetVersion();],
+                success=yes, success=no)
+        fi
+        if test "$success" = "yes"; then
+            AC_TRY_RUN([#include <v8.h>
+                int main() {
+                    int major, minor, micro, nano;
+                    sscanf(v8::V8::GetVersion(), "%d.%d.%d.%d", &major, &minor, &micro, &nano);
+                    int version = (major * 1000000000)
+                                + (minor * 1000000)
+                                + (micro * 1000)
+                                + nano;
+                    if (version >= $v8_version_req_number) {
+                        return 0;
+                    }
+                    else {
+                        return 1;
+                    }
+                }
+                ], [success=yes], [success=no])
+        fi
+        AC_LANG_POP([C++])
+
+        CPPFLAGS="$saved_CPPFLAGS"
+        LDFLAGS="$saved_LDFLAGS"
+
+        if test "$success" = "yes"; then
+            AC_MSG_RESULT([found in $ac_v8_path])
+
+            V8_CPPFLAGS="$ac_v8_cppflags"
+            V8_LDFLAGS="$ac_v8_ldflags"
+
+            AC_SUBST(V8_CPPFLAGS)
+            AC_SUBST(V8_LDFLAGS)
+            AC_DEFINE([HAVE_V8], [], [Have the V8 library])
+            ifelse([$2], , :, [$2])
+        else
+            AC_MSG_RESULT([not found])
+            ifelse([$3], , :, [$3])
+        fi
+    fi
+])
diff --git a/configure.ac b/configure.ac
index 67fc4cf..c7bf9a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -925,6 +925,25 @@ AM_CONDITIONAL(X11_TESTS, [test "x$SUPPORT_X11" = "xyes"])
 AM_CONDITIONAL(SUPPORT_X11, [test "x$SUPPORT_X11" = "xyes"])
 AM_CONDITIONAL(SUPPORT_XLIB, [test "x$SUPPORT_XLIB" = "xyes"])
 
+dnl     ============================================================
+dnl     Check for v8 JavaScript bindings support
+dnl     ============================================================
+AC_ARG_ENABLE(
+  [v8-bindings],
+  [AC_HELP_STRING([--enable-v8-bindings=@<:@no/yes@:>@], [Enable support for v8 JavaScript bindings @<:@default=no@:>@])],
+  [],
+  enable_v8_bindings=no
+)
+V8_CPPFLAGS=""
+SUPPORT_V8_BINDINGS=no
+AS_IF([test "x$enable_v8_bindings" == "xyes"],
+      [
+        AX_LIB_V8(3.3.10)
+        AS_IF([test "$V8_CPPFLAGS" != ""],
+              [SUPPORT_V8_BINDINGS=yes])
+      ])
+AM_CONDITIONAL(SUPPORT_V8_BINDINGS, [test "x$SUPPORT_V8_BINDINGS" == "xyes"])
+
 
 dnl ================================================================
 dnl Compiler stuff.
@@ -1137,6 +1156,8 @@ tests/conform/Makefile
 tests/conform/config.env
 tests/conform/test-launcher.sh
 tests/data/Makefile
+bindings/Makefile
+bindings/v8/Makefile
 po/Makefile.in
 )
 
@@ -1178,6 +1199,11 @@ echo "        Enable deprecated symbols: ${enable_deprecated}"
 echo "        Compiler flags: ${CFLAGS} ${COGL_EXTRA_CFLAGS}"
 echo "        Linker flags: ${LDFLAGS} ${COGL_EXTRA_LDFLAGS}"
 
+# Bindings
+echo ""
+echo " â Bindings:"
+echo "        V8: ${SUPPORT_V8_BINDINGS}"
+
 # Miscellaneous
 echo ""
 echo " â Extra:"



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