summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorØyvind Kolås <pippin@gimp.org>2014-05-23 02:22:45 +0200
committerØyvind Kolås <pippin@gimp.org>2014-05-25 02:58:49 +0200
commit3e184d1bfdb9110901aeb6931db8dafda8485f34 (patch)
treec0816f4df40b83c0c04c00b547d4f5cf66104fc5 /tools
parentf4bc3725668f6784e1c4892505bcd3c35fb20ddc (diff)
op-reference: generate a .json dump instead of HTML
Diffstat (limited to 'tools')
-rw-r--r--tools/operation_reference.c502
1 files changed, 271 insertions, 231 deletions
diff --git a/tools/operation_reference.c b/tools/operation_reference.c
index 35ee4862..42193531 100644
--- a/tools/operation_reference.c
+++ b/tools/operation_reference.c
@@ -1,11 +1,5 @@
#include "config.h"
-
-#include <gegl-plugin.h> /* needed to do full introspection */
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
+#include <gegl-plugin.h>
static GList *
gegl_operations_build (GList *list, GType type)
@@ -58,17 +52,57 @@ static GList *gegl_operations (void)
GeglColor *
gegl_param_spec_color_get_default (GParamSpec *self);
+/* convert operation name to path of example image */
+static gchar*
+operation_to_path (const gchar *op_name)
+{
+ gchar *cleaned = g_strdup (op_name);
+ gchar *filename, *output_path;
+
+ g_strdelimit (cleaned, ":", '-');
+ filename = g_strconcat (cleaned, ".png", NULL);
+ output_path = g_build_path (G_DIR_SEPARATOR_S, "images", "examples", filename, NULL);
+
+ g_free (cleaned);
+ g_free (filename);
+
+ return output_path;
+}
+
+static void json_escape_string (const char *description)
+{
+ const char *p;
+ if (!description)
+ return;
+ for (p = description; *p; p++)
+ {
+ switch (*p)
+ {
+ case '"':
+ case '\\':
+ case '/':
+ g_print ("\\%c", *p);
+ break;
+ case '\n':
+ g_print ("\\n");
+ break;
+ default:
+ g_print ("%c", *p);
+ }
+ }
+}
static void
-list_properties (GType type,
- gint indent,
- gboolean html)
+json_list_properties (GType type, const gchar *opname)
{
GParamSpec **self;
GParamSpec **parent;
guint n_self;
guint n_parent;
gint prop_no;
+ gboolean first_prop = TRUE;
+
+ g_print (",'properties':[\n");
if (!type)
return;
@@ -81,6 +115,7 @@ list_properties (GType type,
G_OBJECT_CLASS (g_type_class_ref (GEGL_TYPE_OPERATION)),
&n_parent);
+
for (prop_no=0;prop_no<n_self;prop_no++)
{
gint parent_no;
@@ -95,10 +130,30 @@ list_properties (GType type,
{
const gchar *type_name = g_type_name (G_OBJECT_TYPE (self[prop_no]));
- type_name = strstr (type_name, "Param");
- type_name+=5;
+ if (first_prop)
+ {
+ first_prop = FALSE;
+ g_print(" { 'name':'%s'\n", g_param_spec_get_name (self[prop_no]));
+ }
+ else
+ g_print(",{'name':'%s'\n", g_param_spec_get_name (self[prop_no]));
+
+ g_print(" ,'label':\"");
+ json_escape_string (g_param_spec_get_nick (self[prop_no]));
+ g_print ("\"\n");
- g_print("<tr><td colspan='1'>&nbsp;&nbsp;</td><td colspan='1' class='prop_type' valign='top'>%s<br/><span style='font-style:normal;text-align:right;float:right;padding-right:1em;'>", type_name);
+ if(strstr (type_name, "Param"))
+ {
+ type_name = strstr (type_name, "Param");
+ type_name+=5;
+ }
+
+ g_print(" ,'type':'");
+ {
+ for (const char *p = type_name; *p; p++)
+ g_print("%c", g_ascii_tolower (*p));
+ }
+ g_print("'\n");
if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (self[prop_no]), G_TYPE_DOUBLE))
{
@@ -107,24 +162,43 @@ list_properties (GType type,
gdouble max = G_PARAM_SPEC_DOUBLE (self[prop_no])->maximum;
if (default_value<-10000000)
- g_print ("-inf ");
+ g_print (" ,'default':'-inf'\n");
else if (default_value>10000000)
- g_print ("+inf");
+ g_print (" ,'default':'+inf'\n");
else
- g_print ("%2.2f", default_value);
+ g_print (" ,'default':'%2.2f'\n", default_value);
- g_print ("<br/>");
if (min<-10000000)
- g_print ("-inf ");
+ g_print (" ,'minimum':'-inf'\n");
else
- g_print ("%2.2f", min);
-
- g_print ("-");
+ g_print (" ,'minimum':'%2.2f'\n", min);
if (max>10000000)
- g_print (" +inf");
+ g_print (" ,'maximum':'+inf'\n");
else
- g_print ("%2.2f", max);
+ g_print (" ,'maximum':'%2.2f'\n", max);
+
+ if (GEGL_IS_PARAM_SPEC_DOUBLE (self[prop_no]))
+ {
+ GeglParamSpecDouble *pspec =
+ GEGL_PARAM_SPEC_DOUBLE (self[prop_no]);
+
+ if (pspec->ui_minimum < -10000000)
+ g_print (" ,'ui-minimum':'-inf'\n");
+ else
+ g_print (" ,'ui-minimum':'%2.2f'\n", pspec->ui_minimum);
+
+ if (pspec->ui_maximum > 10000000)
+ g_print (" ,'ui-maximum':'+inf'\n");
+ else
+ g_print (" ,'ui-maximum':'%2.2f'\n", pspec->ui_maximum);
+
+ g_print (" ,'ui-gamma':'%2.2f'\n", pspec->ui_gamma);
+ g_print (" ,'ui-step-small':'%2.2f'\n", pspec->ui_step_small);
+ g_print (" ,'ui-step-big':'%2.2f'\n", pspec->ui_step_big);
+ g_print (" ,'ui-digits':'%i'\n", pspec->ui_digits);
+ }
+
}
else if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (self[prop_no]), G_TYPE_INT))
{
@@ -133,67 +207,55 @@ list_properties (GType type,
gint max = G_PARAM_SPEC_INT (self[prop_no])->maximum;
if (default_value<-10000000)
- g_print ("-inf ");
+ g_print (" ,'default':'-inf'\n");
else if (default_value>10000000)
- g_print ("+inf");
+ g_print (" ,'default':'+inf'\n");
else
- g_print ("%i", default_value);
+ g_print (" ,'default':'%i'\n", default_value);
- g_print ("<br/>");
if (min<-10000000)
- g_print ("-inf ");
+ g_print (" ,'minimum':'-inf'\n");
else
- g_print ("%i", min);
-
- g_print ("-");
+ g_print (" ,'minimum':'%i'\n", min);
if (max>10000000)
- g_print (" +inf");
+ g_print (" ,'maximum':'+inf'\n");
else
- g_print ("%i", max);
- }
- else if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (self[prop_no]), G_TYPE_FLOAT))
- {
- gfloat default_value = G_PARAM_SPEC_FLOAT (self[prop_no])->default_value;
- gfloat min = G_PARAM_SPEC_FLOAT (self[prop_no])->minimum;
- gfloat max = G_PARAM_SPEC_FLOAT (self[prop_no])->maximum;
+ g_print (" ,'maximum':'%i'\n", max);
- if (default_value<-10000000)
- g_print ("-inf ");
- else if (default_value>10000000)
- g_print ("+inf");
- else
- g_print ("%2.2f", default_value);
+ if (GEGL_IS_PARAM_SPEC_INT (self[prop_no]))
+ {
+ GeglParamSpecInt *pspec =
+ GEGL_PARAM_SPEC_INT (self[prop_no]);
- g_print ("<br/>");
- if (min<-10000000)
- g_print ("-inf ");
- else
- g_print ("%2.2f", min);
+ if (pspec->ui_minimum < -10000000)
+ g_print (" ,'ui-minimum':'-inf'\n");
+ else
+ g_print (" ,'ui-minimum':'%i'\n", pspec->ui_minimum);
- g_print ("-");
+ if (pspec->ui_maximum > 10000000)
+ g_print (" ,'ui-maximum':'+inf'\n");
+ else
+ g_print (" ,'ui-maximum':'%i'\n", pspec->ui_maximum);
+
+ g_print (" ,'ui-gamma':'%2.2f'\n", pspec->ui_gamma);
+ g_print (" ,'ui-step-small':'%i'\n", pspec->ui_step_small);
+ g_print (" ,'ui-step-big':'%i'\n", pspec->ui_step_big);
+ }
- if (max>10000000)
- g_print (" +inf");
- else
- g_print ("%2.2f", max);
}
else if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (self[prop_no]), G_TYPE_BOOLEAN))
{
- g_print ("%s", G_PARAM_SPEC_BOOLEAN (self[prop_no])->default_value?"True":"False");
+ g_print (" ,'default':'%s'\n", G_PARAM_SPEC_BOOLEAN (self[prop_no])->default_value?"True":"False");
}
else if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (self[prop_no]), G_TYPE_STRING))
{
const gchar *string = G_PARAM_SPEC_STRING (self[prop_no])->default_value;
- if (strlen (string) > 8)
- {
- gchar copy[16];
- g_snprintf (copy, 12, "%s..", string);
- g_print ("%s", copy);
- }
- else
- g_print ("%s", string);
+ g_print (" ,'default':\"");
+ json_escape_string (string);
+ g_print ("\"\n");
+
}
else if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (self[prop_no]), GEGL_TYPE_COLOR))
{
@@ -203,7 +265,9 @@ list_properties (GType type,
gchar *string;
g_object_get (color, "string", &string, NULL);
- g_print ("%s", string);
+ g_print (" ,'default':\"");
+ json_escape_string (string);
+ g_print ("\"\n");
g_free (string);
g_object_unref (color);
@@ -211,213 +275,189 @@ list_properties (GType type,
}
else
{
- g_print ("\n");
}
- g_print ("</span></td>");
-
- g_print("<td class='prop_name' valign='top'>%s</td>\n",
- g_param_spec_get_name (self[prop_no]));
if (g_param_spec_get_blurb (self[prop_no]) &&
g_param_spec_get_blurb (self[prop_no])[0]!='\0')
- g_print ("<td colspan='1' valign='top' class='prop_blurb'>%s</td>\n",
- g_param_spec_get_blurb (self[prop_no]));
- else
- g_print ("<td><em>not documented</em></td>\n\n");
+ {
+ g_print (" ,'description':\"");
+
+ json_escape_string (g_param_spec_get_blurb (self[prop_no]));
+ g_print ("\"\n");
+ }
+
+ {
+ guint count;
+ gchar **property_keys = gegl_operation_list_property_keys (
+ opname,
+ g_param_spec_get_name (self[prop_no]),
+
+ &count);
- g_print ("</tr>\n");
+ if (property_keys)
+ {
+ int i;
+ if (property_keys[0])
+ {
+ gboolean first = TRUE;
+ g_print (" ,'meta':[\n");
+ for (i = 0; property_keys[i]; i++)
+ {
+ if (first)
+ {
+ g_print (" ");
+ first = FALSE;
+ }
+ else
+ g_print (" ,");
+ g_print ("['%s','%s']\n",
+ property_keys[i],
+ gegl_operation_get_property_key (opname,
+ g_param_spec_get_name (self[prop_no]),
+ property_keys[i]));
+ }
+ g_print (" ]\n");
+ }
+ g_free (property_keys);
+ }
+ }
+ g_print(" }");
}
}
if (self)
g_free (self);
if (parent)
g_free (parent);
-}
-
-
-static gchar *html_top = "<html>\n<head>\n<title>GEGL operations</title>\n<link rel='shortcut icon' href='images/gegl.ico'/>\n<style type='text/css'>\n@import url(gegl.css);\ndiv#toc ul { font-size:70%; }\n"
-".category { margin-bottom: 2em; }\n"
-".category a {\n display: block;\n width: 14em;\n height: 1.2em;\n float: left;\n text-align: left;\n font-size: 90%;\n}\n"
-"</style>\n<meta http-equiv='Content-Type' content='application/xhtml+xml; charset=UTF-8' /></head>\n\n<body>\n<div class='paper'>\n<div class='content'>\n";
-static gchar *html_bottom = "</div>\n</div>\n</body>\n</html>\n";
-
-
-static void category_index (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- gchar *category = key;
- GList *operations = value;
- GList *iter;
- gboolean comma;
-
- if (!strcmp (category, "hidden"))
- return;
- g_print ("<a name='cat_%s'></a><h3>%s</h3>\n", category, category);
- g_print ("<div class='category'>\n");
-
- for (iter=operations, comma=FALSE;iter;iter = g_list_next (iter))
- {
- GeglOperationClass *klass = iter->data;
- const char *categories = gegl_operation_class_get_key (klass, "categories");
- if (categories && strstr (categories, "hidden"))
- continue;
- g_print ("%s<a href='#op_%s'>%s</a>\n", comma?"":"", klass->name, klass->name);
- comma = TRUE;
- }
- g_print ("<div style='clear:both;'></div></div>\n");
-}
-
-#if 0
-static void category_menu_index (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- gchar *category = key;
- GList *operations = value;
- GList *iter;
-
- if (!strcmp (category, "hidden"))
- return;
- for (iter=operations;iter;iter = g_list_next (iter))
- {
- GeglOperationClass *klass = iter->data;
- const char *categories = gegl_operation_class_get_key (klass, "categories");
- if (!categories || strstr (categories, "hidden"))
- continue;
- g_print ("<li><a href='#op_%s'>%s</a></li>\n", klass->name, klass->name);
- }
-}
-#endif
-
-/* convert operation name to path of example image */
-static gchar*
-operation_to_path (const gchar *op_name)
-{
- gchar *cleaned = g_strdup (op_name);
- gchar *filename, *output_path;
-
- g_strdelimit (cleaned, ":", '-');
- filename = g_strconcat (cleaned, ".png", NULL);
- output_path = g_build_path (G_DIR_SEPARATOR_S, "images", "examples", filename, NULL);
-
- g_free (cleaned);
- g_free (filename);
-
- return output_path;
+ g_print ("]");
}
gint
-main (gint argc,
- gchar **argv)
+main (gint argc, gchar **argv)
{
GList *operations;
GList *iter;
- GHashTable *categories = NULL;
+ gboolean first = TRUE;
gegl_init (&argc, &argv);
operations = gegl_operations ();
- /* Collect categories */
- categories = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ g_print ("window.opdb=[\n");
+
for (iter=operations;iter;iter = g_list_next (iter))
{
GeglOperationClass *klass = iter->data;
+
+
+ const char *name = gegl_operation_class_get_key (klass, "name");
+ const char *description = gegl_operation_class_get_key (klass, "description");
const char *categoris = gegl_operation_class_get_key (klass, "categories");
- const gchar *ptr = categoris;
- while (ptr && *ptr)
- {
- gchar category[64]="";
- gint i=0;
- while (*ptr && *ptr!=':' && i<63)
- {
- category[i++]=*(ptr++);
- category[i]='\0';
- }
- if (*ptr==':')
- ptr++;
- {
- GList *items = g_hash_table_lookup (categories, category);
- g_hash_table_insert (categories, g_strdup (category), g_list_append (items, klass));
- }
- }
- }
- g_print ("%s", html_top);
-
-#if 0
- g_print ("<div id='toc'>\n<ul>\n");
- g_print ("<li><a href='index.html'>GEGL</a></li><li>&nbsp;</li>\n");
- g_print ("<li><a href='index.html#Documentation'>Documentation</a></li>\n");
- g_print ("<li><a href='index.html#Glossary'>&nbsp;&nbsp;Glossary</a></li>\n");
- g_print ("<li><a href='operations.html#'>&nbsp;&nbsp;Operations</a></li>\n");
- g_print ("<li><a href='api.html'>&nbsp;&nbsp;API reference</a></li>\n");
- g_print ("<li><a href=''>&nbsp;</a></li>\n");
- g_print ("<li><a href='#Categories'>Categories</a></li>\n");
- g_print ("<li><a href=''>&nbsp;</a></li>\n");
- /*category_menu_item ("All", NULL, NULL);
- g_hash_table_foreach (categories, category_menu_item, NULL);*/
-
- /*border: 0.1em dashed rgb(210,210,210);
- */
- //category_menu_index("All", operations, NULL);
+ if (first)
+ first = FALSE;
+ else
+ g_print (",");
- g_print ("</ul>\n</div>\n");
-#endif
+ g_print ("{'op':'%s'\n", name);
- g_print ("<h1>GEGL operation reference</h1>");
- g_print ("<p>Image processing operations are shared objects (plug-ins) loaded when GEGL initializes. "
- "This page is generated from information registered by the plug-ins themselves.</p>"
- "<a name='Categories'><h2>Categories</h2></a><p>A plug-in can "
- "belong in multiple categories. Below is indexes broken down into the various available categories.</p>");
+ if (klass->compat_name)
+ g_print (",'compat-op':'%s'\n", klass->compat_name);
- category_index ("All", operations, NULL);
- /* create menus for each of the categories */
+ if (klass->opencl_support)
+ g_print (",'opencl-support':'true'\n");
- g_hash_table_foreach (categories, category_index, NULL);
+ if (description)
+ {
+ g_print (",'description':\"");
+ json_escape_string (description);
+ g_print ("\"\n");
+ }
- /* list all operations */
- g_print ("<table>\n");
- for (iter=operations;iter;iter = g_list_next (iter))
- {
- GeglOperationClass *klass = iter->data;
- const char *categoris = gegl_operation_class_get_key (klass, "categories");
- const char *description = gegl_operation_class_get_key (klass, "description");
- const char *name = gegl_operation_class_get_key (klass, "name");
- if (categoris && strstr (categoris, "hidden"))
- continue;
+ g_print (",'parent':'%s'\n",
+ g_type_name (g_type_parent(G_OBJECT_CLASS_TYPE(klass))));
- g_print ("<tr>\n <td colspan='1'>&nbsp;</td>\n <td class='op_name' colspan='4'><a name='op_%s'>%s</a></td>\n</tr>\n", klass->name, klass->name);
+ {
+ char *image = operation_to_path (name);
- if (name)
- {
- char *image = operation_to_path (name);
+ if (g_file_test (image, G_FILE_TEST_EXISTS))
+ g_print (",'image':'%s'\n", image);
+ g_free (image);
+ }
- if (g_file_test (image, G_FILE_TEST_EXISTS))
- g_print ("<tr>\n <td colspan='1'>&nbsp;</td>\n <td colspan='4'><img style='float:right;padding-left:1.5em;' src='%s' />", image);
- else
- g_print ("<tr>\n <td colspan='1'>&nbsp;</td>\n");
- if (description)
- g_print ("%s\n", description);
- g_print ("</td></tr>\n");
- g_free (image);
- }
- else
- if (description)
- g_print ("<tr>\n <td colspan='1'>&nbsp;</td>\n <td class='op_description' colspan='4'>%s</td>\n</tr>\n", description);
+ if (categoris)
+ {
+ const gchar *ptr = categoris;
+ gboolean first = TRUE;
+ g_print (",'categories':[");
- list_properties (G_OBJECT_CLASS_TYPE (klass), 2, TRUE);
- }
- g_print ("</table>\n");
+ while (ptr && *ptr)
+ {
+ gchar category[64]="";
+ gint i=0;
+ while (*ptr && *ptr!=':' && i<63)
+ {
+ category[i++]=*(ptr++);
+ category[i]='\0';
+ }
+ if (*ptr==':')
+ ptr++;
+ {
+ if (first)
+ first = FALSE;
+ else
+ g_print (",");
+ g_print ("'%s'", category);
+ }
+ }
+ g_print ("]\n");
+ }
+
+ json_list_properties (G_OBJECT_CLASS_TYPE (klass), name);
+ {
+ guint nkeys;
+ gchar **keys = gegl_operation_list_keys (name, &nkeys);
- g_print ("%s", html_bottom);
+ if (keys)
+ {
+ gboolean first_key = TRUE;
+ for (gint i = 0; keys[i]; i++)
+ {
+ const gchar *value = gegl_operation_get_key (name, keys[i]);
+
+ if (g_str_equal (keys[i], "categories") ||
+ g_str_equal (keys[i], "cl-source") ||
+ g_str_equal (keys[i], "name") ||
+ g_str_equal (keys[i], "description")
+ )
+ continue;
+
+ if (first_key)
+ {
+ g_print (",'meta':[\n");
+ g_print (" ");
+ first_key = FALSE;
+ }
+ else
+ {
+ g_print (" ,");
+ }
+ g_print ("[\"%s\", \"", keys[i]);
+ json_escape_string (value);
+ g_print ("\"]\n");
+ }
+ g_free (keys);
+ if (!first_key)
+ g_print ("]\n");
+ }
+ }
+
+ g_print (" }\n");
+ }
+ g_print ("]\n");
- g_list_free (operations);
- gegl_exit ();
return 0;
}