From: ntakahas Date: Fri, 9 Apr 2010 04:52:26 +0000 (+0000) Subject: New file. X-Git-Url: http://git.chise.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2FXML;p=m17n%2Fm17n-lib.git New file. --- diff --git a/src/flt-xml.c b/src/flt-xml.c new file mode 100644 index 0000000..8d51d07 --- /dev/null +++ b/src/flt-xml.c @@ -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 +#include +#include +#include +#include +#include + +#include "/usr/local/work/m17n-lib-xml/src/config.h" +#include +#include +#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; +}