New file. XML
authorntakahas <ntakahas>
Fri, 9 Apr 2010 04:52:26 +0000 (04:52 +0000)
committerntakahas <ntakahas>
Fri, 9 Apr 2010 04:52:26 +0000 (04:52 +0000)
src/flt-xml.c [new file with mode: 0644]

diff --git a/src/flt-xml.c b/src/flt-xml.c
new file mode 100644 (file)
index 0000000..8d51d07
--- /dev/null
@@ -0,0 +1,620 @@
+/* m17n-flt-xml.c -- XML Font Layout Table sub-module.
+   Copyright (C) 2009
+     National Institute of Advanced Industrial Science and Technology (AIST)
+     Registration Number H15PRO112
+
+   This file is part of the m17n library.
+
+   The m17n library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   The m17n 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 the m17n library; if not, write to the Free
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   02111-1307, USA.  */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+#include "/usr/local/work/m17n-lib-xml/src/config.h"
+#include <m17n.h>
+#include <m17n-misc.h>
+#include "/usr/local/work/m17n-lib-xml/src/internal.h"
+#include "/usr/local/work/m17n-lib-xml/src/database.h"
+
+#define STRCAT(dest, src)                                              \
+  do {                                                                 \
+    dest = realloc (dest, strlen (dest) + strlen ((char *) src) + 1);  \
+    strcat (dest, (char *) src);                                       \
+  } while (0)
+
+
+static void
+decode_otf_specification (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlNodePtr cur0;
+  xmlChar *ptr;
+  char *p = malloc (6);
+
+  sprintf (p, ":otf=");
+
+  ptr = xmlGetProp (cur, (xmlChar *) "script");
+  STRCAT (p, ptr);
+  xmlFree (ptr);
+  
+  if ((ptr = xmlGetProp (cur, (xmlChar *) "langsys")))
+    {
+      STRCAT(p, "/");
+      STRCAT(p, ptr);
+      xmlFree (ptr);
+    }      
+
+  cur = cur->xmlChildrenNode;
+
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "gsub-features"))
+    {
+      cur0 = cur->xmlChildrenNode;
+      if (xmlStrEqual (cur0->name, (xmlChar *) "positive-list"))
+       {
+         STRCAT(p, "=");
+         for (cur0 = cur0->xmlChildrenNode; cur0; cur0 = cur0->next)
+           {
+             if (p[strlen (p) - 1] != '=')
+               STRCAT (p, ",");
+             ptr = xmlNodeListGetString (doc, cur0->xmlChildrenNode, 1);
+             STRCAT (p, ptr);
+             xmlFree (ptr);
+           }
+       }
+      else if (cur0->xmlChildrenNode) /* at least one negative element */
+       {
+         STRCAT(p, "=");
+         for (cur0 = cur0->xmlChildrenNode; cur0; cur0 = cur0->next)
+           {
+             if (p[strlen (p) - 1] != '=')
+               STRCAT (p, ",");
+             STRCAT (p, "~");
+             ptr = xmlNodeListGetString (doc, cur0->xmlChildrenNode, 1);
+             STRCAT (p, ptr);
+             xmlFree (ptr);
+           }
+         STRCAT(p, ",*");
+       }
+      cur = cur->next;
+    }
+
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "gpos-features"))
+    {
+      cur0 = cur->xmlChildrenNode;
+      if (xmlStrEqual (cur0->name, (xmlChar *) "positive-list"))
+       {
+         STRCAT(p, "+");
+         for (cur0 = cur0->xmlChildrenNode; cur0; cur0 = cur0->next)
+           {
+             if (p[strlen (p) - 1] != '+')
+               STRCAT (p, ",");
+             ptr = xmlNodeListGetString (doc, cur0->xmlChildrenNode, 1);
+             STRCAT (p, ptr);
+             xmlFree (ptr);
+           }
+       }
+      else if (cur0->xmlChildrenNode) /* at least one negative element */
+       {
+         STRCAT(p, "+");
+         for (cur0 = cur0->xmlChildrenNode; cur0; cur0 = cur0->next)
+           {
+             if (p[strlen (p) - 1] != '+')
+               STRCAT (p, ",");
+             STRCAT (p, "~");
+             ptr = xmlNodeListGetString (doc, cur0->xmlChildrenNode, 1);
+             STRCAT (p, ptr);
+             xmlFree (ptr);
+           }
+         STRCAT(p, ",*");
+       }
+    }
+
+  mplist_add (parent, Msymbol, msymbol (p));
+  free (p);
+}
+
+static void
+decode_lang_specification (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  char *p = malloc (7);
+
+  sprintf (p, ":lang=");
+
+  while (cur)
+    {
+      if (p[strlen (p) - 1] != '=')
+       STRCAT (p, ",");
+      ptr = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+      STRCAT (p, ptr);
+      xmlFree (ptr);
+      cur = cur->next;
+    }
+
+  mplist_add (parent, Msymbol, msymbol (p));
+  free (p);
+}
+
+static void
+decode_font (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+
+  if ((ptr = xmlGetProp (cur, (xmlChar *) "foundry")))
+    {
+      mplist_add (parent, Msymbol, msymbol ((char *) ptr));
+      xmlFree (ptr);
+      ptr = xmlGetProp (cur, (xmlChar *) "family");
+      mplist_add (parent, Msymbol, msymbol ((char *) ptr));
+      xmlFree (ptr);
+      if ((ptr = xmlGetProp (cur, (xmlChar *) "weight")))
+       {
+         mplist_add (parent, Msymbol, msymbol ((char *) ptr));
+         xmlFree (ptr);
+         if ((ptr = xmlGetProp (cur, (xmlChar *) "style")))
+           {
+             mplist_add (parent, Msymbol, msymbol ((char *) ptr));
+             xmlFree (ptr);
+             if ((ptr = xmlGetProp (cur, (xmlChar *) "stretch")))
+               {
+                 mplist_add (parent, Msymbol, msymbol ((char *) ptr));
+                 xmlFree (ptr);
+                 if ((ptr = xmlGetProp (cur, (xmlChar *) "adstyle")))
+                   {
+                     mplist_add (parent, Msymbol, msymbol ((char *) ptr));
+                     xmlFree (ptr);
+                   }
+               }
+           }
+       }
+    }
+
+  if ((ptr = xmlGetProp (cur, (xmlChar *) "registry")))
+    {
+      mplist_add (parent, Msymbol, msymbol ((char *) ptr));
+      xmlFree (ptr);
+    }
+
+  cur = cur->xmlChildrenNode;
+
+  if (cur && xmlStrEqual (cur->name, (xmlChar *) "otf-specification"))
+    {
+      decode_otf_specification (doc, cur, parent);
+      cur = cur->next;
+    }
+
+  if (cur)
+    decode_lang_specification (doc, cur, parent);
+}
+
+static xmlChar *
+decode_glyph_code (xmlChar *ptr, MPlist *parent)
+{
+  if (xmlStrlen (ptr) >= 3
+      && (ptr[0] == '0' || ptr[0] == '#')
+      && ptr[1] == 'x')
+    {
+      int val;
+
+      sscanf ((char *) ptr + 2, "%x", &val);
+      mplist_add (parent, Minteger, (void *) val);
+      while (*ptr && ! isspace (*ptr))
+       ptr++;
+      while (*ptr && isspace (*ptr))
+       ptr++;
+      return (ptr);
+    }
+  else if (ptr[0] == '?')
+    {
+      int val, len = 4;
+
+      val = xmlGetUTF8Char (ptr + 1, &len);
+      mplist_add (parent, Minteger, (void *) val);
+      return (ptr + 1 + len);
+    }
+  else
+    {
+      mplist_add (parent, Minteger, (void *) atoi ((char *) ptr));
+      while (*ptr && ! isspace (*ptr))
+       ptr++;
+      while (*ptr && isspace (*ptr))
+       ptr++;
+      return (ptr);
+    }
+}
+
+static void
+decode_category_table (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("category"));
+
+  for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+    {
+      xmlChar *ptr;
+      MPlist *plist0 = mplist ();
+
+      ptr = xmlGetProp (cur, (xmlChar *) "code");
+      if (ptr)
+       {
+         decode_glyph_code (ptr, plist0);
+         xmlFree (ptr);
+       }
+      else
+       {
+         ptr = xmlGetProp (cur, (xmlChar *) "from-code");
+         decode_glyph_code (ptr, plist0);
+         xmlFree (ptr);
+         ptr = xmlGetProp (cur, (xmlChar *) "to-code");
+         decode_glyph_code (ptr, plist0);
+         xmlFree (ptr);
+       }
+      ptr = xmlGetProp (cur, (xmlChar *) "category-value");
+      mplist_add (plist0, Msymbol, msymbol ((char *) ptr));
+      xmlFree (ptr);
+
+      mplist_add (plist, Mplist, plist0);
+      M17N_OBJECT_UNREF (plist0);
+    }
+
+  mplist_add (parent, Mplist, plist);
+  M17N_OBJECT_UNREF (plist);
+}
+
+static void
+decode_action (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+
+  if (xmlStrEqual (cur->name, (xmlChar *) "direct-code"))
+    {
+      ptr = xmlGetProp (cur, (xmlChar *) "glyph-code");
+      decode_glyph_code (ptr, parent);
+      xmlFree (ptr);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "copy-glyph"))
+    mplist_add (parent, Msymbol, msymbol ("="));
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "repeat"))
+    mplist_add (parent, Msymbol, msymbol ("*"));
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "start-cluster"))
+    mplist_add (parent, Msymbol, msymbol ("<"));
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "end-cluster"))
+    mplist_add (parent, Msymbol, msymbol (">"));
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "left-padding-flag"))
+    mplist_add (parent, Msymbol, msymbol ("["));
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "right-padding-flag"))
+    mplist_add (parent, Msymbol, msymbol ("]"));
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "separator"))
+    mplist_add (parent, Msymbol, msymbol ("|"));
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "regexp-block"))
+    {
+      MPlist *plist = mplist ();
+
+      ptr = xmlGetProp (cur, (xmlChar *) "regexp");
+      mplist_add (plist, Mtext,
+                 mtext_from_data (ptr, xmlStrlen (ptr), MTEXT_FORMAT_UTF_8));
+
+      for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+       decode_action (doc, cur, plist);
+
+      mplist_add (parent, Mplist, plist);
+      M17N_OBJECT_UNREF (plist);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "match-block"))
+    {
+      MPlist *plist = mplist ();
+
+      ptr = xmlGetProp (cur, (xmlChar *) "match-index");
+      mplist_add (plist, Minteger, (void *) atoi ((char *) ptr));
+      xmlFree (ptr);
+
+      for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+       decode_action (doc, cur, plist);
+
+      mplist_add (parent, Mplist, plist);
+      M17N_OBJECT_UNREF (plist);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "subst-block"))
+    {
+      MPlist *plist = mplist (), *plist0 = mplist ();
+
+      cur = cur->xmlChildrenNode;
+      if (xmlStrEqual (cur->name, (xmlChar *) "source-pattern"))
+       {
+         xmlChar *start = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+
+         for (ptr = start; *ptr; ptr = decode_glyph_code (ptr, plist0));
+         xmlFree (start);
+       }
+      else                     /* code-range */
+       {
+         mplist_add (plist0, Msymbol, msymbol ("range"));
+         ptr = xmlGetProp (cur, (xmlChar *) "from-code");
+         decode_glyph_code (ptr, plist0);
+         xmlFree (ptr);
+         ptr = xmlGetProp (cur, (xmlChar *) "to-code");
+         decode_glyph_code (ptr, plist0);
+         xmlFree (ptr);
+       }
+      mplist_add (plist, Mplist, plist0);
+      M17N_OBJECT_UNREF (plist0);
+
+      for (cur = cur->next; cur; cur = cur->next)
+       decode_action (doc, cur, plist);
+
+      mplist_add (parent, Mplist, plist);
+      M17N_OBJECT_UNREF (plist);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "cond-block"))
+    {
+      MPlist *plist = mplist ();
+
+      mplist_add (plist, Msymbol, msymbol ("cond"));
+
+      for (cur = cur->xmlChildrenNode; cur; cur = cur->next)
+       decode_action (doc, cur, plist);
+
+      mplist_add (parent, Mplist, plist);
+      M17N_OBJECT_UNREF (plist);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "font-facility-block"))
+    {
+      MPlist *plist = mplist (), *plist0 = mplist ();
+
+      mplist_add (plist0, Msymbol, msymbol ("font-facility"));
+
+      cur = cur->xmlChildrenNode;
+      if (xmlStrEqual (cur->name, (xmlChar *) "font"))
+       decode_font (doc, cur, plist0);
+      else                     /* characters */
+       {
+         xmlChar *start = xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
+
+         for (ptr = start; *ptr; ptr = decode_glyph_code (ptr, plist0));
+         xmlFree (start);
+       }
+      mplist_add (plist, Mplist, plist0);
+
+      for (cur = cur->next; cur; cur = cur->next)
+       decode_action (doc, cur, plist);
+
+      mplist_add (parent, Mplist, plist);
+      M17N_OBJECT_UNREF (plist);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "otf-specification"))
+    decode_otf_specification (doc, cur, parent);
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "combining-specification"))
+    {
+      char *v_pos1, *h_pos1, *v_pos2, *h_pos2;
+      char *x_direction, *x_amount, *y_direction, *y_amount;
+      char *combining_name;
+      int len = 6;
+
+      v_pos1 = (char *) xmlGetProp (cur, (xmlChar *) "v-pos1");
+      h_pos1 = (char *) xmlGetProp (cur, (xmlChar *) "h-pos1");
+      v_pos2 = (char *) xmlGetProp (cur, (xmlChar *) "v-pos2");
+      h_pos2 = (char *) xmlGetProp (cur, (xmlChar *) "h-pos2");
+      x_direction = (char *) xmlGetProp (cur, (xmlChar *) "x-direction");
+      x_amount = (char *) xmlGetProp (cur, (xmlChar *) "x-amount");
+      y_direction = (char *) xmlGetProp (cur, (xmlChar *) "y-direction");
+      y_amount = (char *) xmlGetProp (cur, (xmlChar *) "y-amount");
+
+      if (! x_direction && !y_direction)
+       {
+         combining_name = malloc (len);
+         sprintf (combining_name, "%c%c.%c%c",
+                  *v_pos1, *h_pos1, *v_pos2, *h_pos2);
+       }
+      else
+       {
+         if (x_direction)
+           len++;
+         if (x_amount)
+           len += strlen (x_amount);
+         if (y_direction)
+           len++;
+         if (y_amount)
+           len += strlen (y_amount);
+         combining_name = malloc (len);
+         sprintf (combining_name, "%c%c%s%s%s%s%c%c",
+                  *v_pos1, *h_pos1,
+                  ! y_direction ? "" :
+                  (! strcmp (y_direction, "up") ? "+" : "-"),
+                  y_amount ? y_amount : "",
+                  ! x_direction ? "" :
+                  (! strcmp (x_direction, "left") ? ">" : "<"),
+                  x_amount ? x_amount : "",
+                  *v_pos2, *h_pos2);
+       }
+      mplist_add (parent, Msymbol, msymbol (combining_name));
+
+      xmlFree (v_pos1);
+      xmlFree (h_pos1);
+      xmlFree (v_pos2);
+      xmlFree (h_pos2);
+      if (x_direction)
+       xmlFree (x_direction);
+      if (x_amount)
+       xmlFree (x_amount);
+      if (y_direction)
+       xmlFree (y_direction);
+      if (y_amount)
+       xmlFree (y_amount);
+      free (combining_name);
+    }
+
+  else if (xmlStrEqual (cur->name, (xmlChar *) "macro-reference"))
+    {
+      ptr = xmlGetProp (cur, (xmlChar *) "macro-ID");
+      mplist_add (parent, Msymbol, msymbol ((char *) ptr));
+      xmlFree (ptr);
+    }
+
+  else
+    {
+      ptr = cur->name;
+    }
+}
+
+static void
+decode_generator (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  MPlist *plist = mplist ();
+
+  mplist_add (plist, Msymbol, msymbol ("generator"));
+
+  cur = cur->xmlChildrenNode;
+  decode_action (doc, cur, plist);
+
+  /* macro-definition */
+  for (cur = cur->next; cur; cur = cur->next)
+    {
+      xmlNodePtr cur0;
+      xmlChar *ptr;
+      MPlist *plist0 = mplist ();
+
+      ptr = xmlGetProp (cur, (xmlChar *) "macro-ID");
+      mplist_add (plist0, Msymbol, msymbol ((char *) ptr));
+      xmlFree (ptr);
+      for (cur0 = cur->xmlChildrenNode; cur0; cur0 = cur0->next)
+       decode_action (doc, cur0, plist0);
+      mplist_add (plist, Mplist, plist0);
+      M17N_OBJECT_UNREF (plist0);
+    }
+
+  mplist_add (parent, Mplist, plist);
+  M17N_OBJECT_UNREF (plist);
+}
+
+static void
+decode_first_stage (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  cur = cur->xmlChildrenNode;
+  decode_category_table (doc, cur, parent);
+
+  cur = cur->next;
+  decode_generator (doc, cur, parent);
+}
+
+static void
+decode_stage (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  cur = cur->xmlChildrenNode;
+
+  if (xmlStrEqual (cur->name, (xmlChar *) "category-table"))
+    {
+      decode_category_table (doc, cur, parent);
+      cur = cur->next;
+    }
+
+  decode_generator (doc, cur, parent);
+}
+
+static void
+decode_font_layouter (xmlDocPtr doc, xmlNodePtr cur, MPlist *parent)
+{
+  xmlChar *ptr;
+  MPlist *plist = mplist ();
+  MSymbol Mfont = msymbol ("font");
+
+  mplist_add (plist, Msymbol, Mfont);
+  mplist_add (plist, Msymbol, msymbol ("layouter"));
+
+  ptr = xmlGetProp (cur, (xmlChar *) "key0");
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+  xmlFree (ptr);
+
+  ptr = xmlGetProp (cur, (xmlChar *) "key1");
+  mplist_add (plist, Msymbol, msymbol ((char *) ptr));
+  xmlFree (ptr);
+
+  cur = xmlDocGetRootElement (doc)->xmlChildrenNode;
+
+  if (xmlStrEqual (cur->name, (xmlChar *) "font"))
+    {
+      MPlist *plist0 = mplist (), *plist1 = mplist ();
+
+      mplist_add (plist0, Msymbol, Mfont);
+      decode_font (doc, cur, plist1);
+      mplist_add (plist0, Mplist, plist1);
+      mplist_add (plist, Mplist, plist0);
+      M17N_OBJECT_UNREF (plist0);
+      M17N_OBJECT_UNREF (plist1);
+      cur = cur->next;
+    }
+
+  mplist_add (parent, Mplist, plist);
+  M17N_OBJECT_UNREF (plist);
+
+  decode_first_stage (doc, cur, parent);
+
+  for (cur = cur->next; cur; cur = cur->next)
+    decode_stage (doc, cur, parent);
+}
+
+MPlist *
+mflt__load_xml (MDatabaseInfo *db_info, char *filename)
+{
+  xmlDocPtr doc;
+  xmlNodePtr cur;
+  MPlist *xml = mplist ();
+
+  doc = xmlReadFile (filename, NULL, XML_PARSE_NOENT | XML_PARSE_NOBLANKS);
+  if (! doc)
+    return NULL;
+
+  cur = xmlDocGetRootElement (doc);
+  if (! cur)
+    {
+      xmlFreeDoc (doc);
+      return NULL;
+    }
+
+  if (xmlStrcmp (cur->name, (xmlChar *) "font-layouter"))
+    {
+      xmlFreeDoc (doc);
+      return NULL;
+    }
+
+  if (! mdatabase__validate (doc, db_info))
+    {
+      xmlFreeDoc (doc);
+      MERROR (MERROR_IM, NULL);
+    }
+
+  decode_font_layouter (doc, cur, xml);
+
+  xmlFreeDoc (doc);
+  return xml;
+}