(create_otf_script_widgets): Create a box
[m17n/libotf.git] / example / otfview.c
index 739fd47..82c3cfe 100644 (file)
@@ -1,6 +1,6 @@
 /* otfview.c -- View glyphs of OpenType fonts.
 
-Copyright (C) 2003, 2004, 2005, 2006, 2008
+Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010
   National Institute of Advanced Industrial Science and Technology (AIST)
   Registration Number H15PRO167
 
@@ -85,6 +85,9 @@ XtAppContext context;
    | | idxh[7] glyph[112]  ...    glyph[127]| |
    | |         idxl[0]     ...    idxl[15]  | |
    | +--------------------------------------+ |
+   | +--- script_area (box) ----------------+ |
+   | | script(langsys) DFLT ...             | |
+   | +--------------------------------------+ |
    | +---- uvs_area (box) (optional) -------+ |
    | | uvs[?].w ...                         | |
    | +--------------------------------------+ |
@@ -98,6 +101,9 @@ XtAppContext context;
    | | +--- seq (box) --------------------+ | |
    | | | seq_label seq_image              | | |
    | | +----------------------------------+ | |
+   | | +--- code (box) -------------------+ | |
+   | | | code_label code_list ...         | | |   
+   | | +----------------------------------+ | |
    | +--------------------------------------+ |
    +------------------------------------------+ */
 Widget shell, frame;
@@ -105,8 +111,8 @@ Widget command_area, quit, dump, *charmap;
 Widget navi_area, FIRST, PREV, prev, range, next, NEXT, LAST;
 Widget glyph_area, glyph[128], index_label[8];
 Widget uvs_area, uvs_label;
-Widget render_area, clear, del, bidi, alt_subst, raw, seq;
-Widget raw_label, raw_image, seq_label, seq_image;
+Widget render_area, clear, del, bidi, alt_subst, raw, seq, code;
+Widget raw_label, raw_image, seq_label, seq_image, code_label, code_list;
 unsigned long foreground, background;
 
 typedef struct
@@ -293,21 +299,21 @@ get_features (OTF_FeatureList *list, FeatureRec *rec)
   int i, n;
   char *str, *p;
 
-  if (! rec->langsys || ! rec->features || ! rec->features[0].on)
+  if (! rec->langsys || ! rec->features)
     return NULL;
   for (i = n = 0; i < rec->langsys->FeatureCount; i++)
-    {
-      if (rec->features[i].on)
-       n++;
-      else
-       break;
-    }
+    if (rec->features[i].on)
+      n++;
+  if (n == 0)
+    return NULL;
   str = malloc (n * 5);
-  for (i = 0, p = str; i < n; i++, p += 5)
-    {
-      OTF_tag_name (rec->features[i].tag, p);
-      p[4] = ',';
-    }
+  for (i = 0, p = str; i < rec->langsys->FeatureCount; i++)
+    if (rec->features[i].on)
+      {
+       OTF_tag_name (rec->features[i].tag, p);
+       p[4] = ',';
+       p += 5;
+      }
   p[-1] = '\0';
   return str;
 }
@@ -353,6 +359,8 @@ update_seq_area ()
   int len = glyph_rec.n_glyphs;
   Arg arg[1];
   int unitsPerEm = face->units_per_EM;
+  OTF_Tag *log = NULL;
+  int logsize;
 
   gstring.size = gstring.used = len;
   gstring.glyphs = malloc (sizeof (OTF_Glyph) * len);
@@ -368,19 +376,45 @@ update_seq_area ()
   XDrawLine (display, seq_pixmap, gc_set, 0, glyph_y, render_width, glyph_y);
   if (otf)
     {
+      char *script_name = NULL, *langsys_name = NULL, buf[10];
       char *str;
 
-      OTF_drive_gdef (otf, &gstring);
+      if (script_tag)
+       {
+         script_name = buf;
+         OTF_tag_name (script_tag, script_name);
+       }
+      if (langsys_tag)
+       {
+         langsys_name = buf + 5;
+         OTF_tag_name (langsys_tag, langsys_name);
+       }
+
       OTF_drive_cmap (otf, &gstring);
+      OTF_drive_gdef (otf, &gstring);
       if (otf->gsub)
        {
          str = get_features (&otf->gsub->FeatureList, &gsub);
          if (str)
            {
              if (do_alternate_subst)
-               OTF_drive_gsub_alternate (otf, &gstring, NULL, NULL, str);
+               OTF_drive_gsub_alternate (otf, &gstring,
+                                         script_name, langsys_name, str);
              else
-               OTF_drive_gsub (otf, &gstring, NULL, NULL, str);
+               {
+                 OTF_drive_gsub_with_log (otf, &gstring,
+                                          script_name, langsys_name, str);
+                 logsize = gstring.used * 2;
+                 log = alloca (sizeof (OTF_Tag) * logsize);
+                 for (i = 0; i < gstring.used; i++)
+                   {
+                     int idx = gstring.glyphs[i].positioning_type >> 4;
+                     if (idx)
+                       log[i] = otf->gsub->FeatureList.Feature[idx - 1].FeatureTag;
+                     else
+                       log[i] = 0;
+                   }
+               }
              free (str);
            }
        }
@@ -389,7 +423,32 @@ update_seq_area ()
          str = get_features (&otf->gpos->FeatureList, &gpos);
          if (str)
            {
-             OTF_drive_gpos2 (otf, &gstring, NULL, NULL, str);
+             OTF_drive_gpos_with_log (otf, &gstring,
+                                      script_name, langsys_name, str);
+             if (log)
+               {
+                 if (logsize < gstring.used)
+                   {
+                     OTF_Tag *log2 = alloca (sizeof (OTF_Tag) * gstring.used);
+                     memset (log2, 0, sizeof (OTF_Tag) * gstring.used);
+                     memcpy (log2, log, sizeof (OTF_Tag) * logsize);
+                     logsize = gstring.used;
+                     log = log2;
+                   }
+               }
+             else
+               {
+                 logsize = gstring.used;
+                 log = alloca (sizeof (OTF_Tag) * logsize);
+                 memset (log, 0, sizeof (OTF_Tag) * logsize);
+               }
+             for (i = 0; i < gstring.used; i++)
+               {
+                 int idx = gstring.glyphs[i].positioning_type >> 4;
+                 if (idx)
+                   log[i] = otf->gpos->FeatureList.Feature[idx - 1].FeatureTag;
+
+               }
              free (str);
            }
        }
@@ -432,22 +491,22 @@ update_seq_area ()
            continue;
          advance = bmp->advance;
        }
-      if (g->positioning_type)
+      if (g->positioning_type & 0xF)
        {
          while (1)
            {
-             switch (g->positioning_type)
+             switch (g->positioning_type & 0xF)
                {
                case 1: case 2:
                  {
                    int format = g->f.f1.format;
 
                    if (format & OTF_XPlacement)
-                     xoff = g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
+                     xoff += g->f.f1.value->XPlacement * pixel_size / unitsPerEm;
                    if (format & OTF_XPlaDevice)
                      xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, pixel_size);
                    if (format & OTF_YPlacement)
-                     yoff = g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
+                     yoff += g->f.f1.value->YPlacement * pixel_size / unitsPerEm;
                    if (format & OTF_YPlaDevice)
                      yoff += DEVICE_DELTA (g->f.f1.value->YPlaDevice, pixel_size);
                    if (format & OTF_XAdvance)
@@ -491,7 +550,7 @@ update_seq_area ()
                }
              if (i + 1 == gstring.used
                  || gstring.glyphs[i + 1].glyph_id
-                 || ! gstring.glyphs[i + 1].positioning_type)
+                 || ! (gstring.glyphs[i + 1].positioning_type & 0xF))
                break;
              i++, g++;
            }
@@ -509,10 +568,43 @@ update_seq_area ()
       else
        base = g, base_width = advance;
     }
-  free (gstring.glyphs);
 
   XtSetArg (arg[0], XtNbitmap, seq_pixmap);
   XtSetValues (seq_image, arg, 1);
+
+  if (gstring.used > 0)
+    {
+      int size = render_width / FONT_WIDTH;
+      char *buf = alloca (size + 1);
+      char name[5];
+
+      sprintf (buf, "%04X", gstring.glyphs[0].glyph_id);
+      if (log && log[0])
+       {
+         OTF_tag_name (log[0], name);
+         sprintf (buf + 4, " (%s)", name);
+         x = 11;
+       }
+      else
+       x = 4;
+      for (i = 1; i < gstring.used && x + 5 < size; i++, x += 5)
+       {
+         sprintf (buf + x, " %04X", gstring.glyphs[i].glyph_id);
+         if (log && log[i] && x + 11 < size)
+           {
+             OTF_tag_name (log[i], name);
+             sprintf (buf + x + 5, "(%s)", name);
+             x += 6;
+           }
+       }
+      while (x < size)
+       buf[x++] = ' ';
+      buf[x] = '\0';
+      XtSetArg (arg[0], XtNlabel, buf);
+      XtSetValues (code_list, arg, 1);
+    }
+
+  free (gstring.glyphs);
 }
 
 
@@ -869,43 +961,35 @@ FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
   if (idx < 0)
     {
       int on = idx == -2;
+      char str[5];
 
-      for (i = j = 0; j < rec->langsys->FeatureCount; j++)
-       {
-         int index  = rec->langsys->FeatureIndex[j];
-
-         rec->features[j].tag
-           = rec->gsub_gpos->FeatureList.Feature[index].FeatureTag;
-         rec->features[j].on = on;
-       }
+      for (i = 0; i < rec->langsys->FeatureCount; i++)
+       if (rec->features[i].on != on)
+         {
+           rec->features[i].on = on;
+           if (on)
+             {
+               XtSetArg (arg[0], XtNborderWidth, 3);
+               XtSetArg (arg[1], XtNinternalHeight, 2);
+               XtSetArg (arg[2], XtNinternalWidth, 2);
+             }
+           else
+             {
+               XtSetArg (arg[0], XtNborderWidth, 1);
+               XtSetArg (arg[1], XtNinternalHeight, 4);
+               XtSetArg (arg[2], XtNinternalWidth, 4);
+             }
+           OTF_tag_name (rec->features[i].tag, str);
+           XtSetArg (arg[3], XtNlabel, str);
+           XtSetValues (rec->features[i].w, arg, 4);
+         }
     }
   else
     {
-      OTF_Tag tag = rec->features[idx].tag;
-
-      i = idx;
-      if (rec->features[i].on)
-       {
-         for (j = i + 1;
-              j < rec->langsys->FeatureCount && rec->features[j].on; j++)
-           rec->features[j - 1].tag = rec->features[j].tag;
-         rec->features[j - 1].tag = tag;
-         rec->features[j - 1].on = 0;
-       }
-      else
-       {
-         for (j = i + 1; i > 0 && ! rec->features[i - 1].on; i--)
-           rec->features[i].tag = rec->features[i - 1].tag;
-         rec->features[i].tag = tag;
-         rec->features[i].on = 1;
-       }
-    }
-
-  for (; i < j; i++)
-    {
       char str[5];
 
-      if (rec->features[i].on)
+      rec->features[idx].on = ! rec->features[idx].on;
+      if (rec->features[idx].on)
        {
          XtSetArg (arg[0], XtNborderWidth, 3);
          XtSetArg (arg[1], XtNinternalHeight, 2);
@@ -917,9 +1001,9 @@ FeatureProc (Widget w, XtPointer client_data, XtPointer call_data)
          XtSetArg (arg[1], XtNinternalHeight, 4);
          XtSetArg (arg[2], XtNinternalWidth, 4);
        }
-      OTF_tag_name (rec->features[i].tag, str);
+      OTF_tag_name (rec->features[idx].tag, str);
       XtSetArg (arg[3], XtNlabel, str);
-      XtSetValues (rec->features[i].w, arg, 4);
+      XtSetValues (rec->features[idx].w, arg, 4);
     }
   update_seq_area ();
 }
@@ -1171,15 +1255,20 @@ create_otf_script_widgets (Widget prev)
     }
   else
     {
+      Widget box;
+      XtSetArg (arg[0], XtNborderWidth, 0);
+      XtSetArg (arg[1], XtNwidth, render_width - (FONT_WIDTH * 15));
+      XtSetArg (arg[2], XtNorientation, XtorientHorizontal);
+      box = XtCreateManagedWidget ("scritp-list", boxWidgetClass, prev, arg, 2);
       XtSetArg (arg[0], XtNstate, True);
-      w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
+      w = XtCreateManagedWidget (name, toggleWidgetClass, box, arg, 1);
       XtAddCallback (w, XtNcallback, ScriptProc, NULL);
       XtSetArg (arg[0], XtNradioGroup, w);
       for (i = 1; i < n; i++)
        {
          compose_script_langsys (script_langsys[i].script,
                                  script_langsys[i].langsys, name);
-         w = XtCreateManagedWidget (name, toggleWidgetClass, prev, arg, 1);
+         w = XtCreateManagedWidget (name, toggleWidgetClass, box, arg, 1);
          XtAddCallback (w, XtNcallback, ScriptProc, NULL);
        }         
     }
@@ -1469,6 +1558,16 @@ create_widgets ()
   XtSetArg (arg[1], XtNbitmap, seq_pixmap);
   seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
                                     seq, arg, 2);
+  XtSetArg (arg[6], XtNfromVert, seq);
+  code = XtCreateManagedWidget ("code", boxWidgetClass, render_area, arg, 7);
+  XtSetArg (arg[0], XtNborderWidth, 0);
+  XtSetArg (arg[1], XtNlabel, "code:");
+  code_label = XtCreateManagedWidget ("code-label", labelWidgetClass,
+                                    code, arg, 2);
+  XtSetArg (arg[1], XtNlabel, "");
+  XtSetArg (arg[2], XtNwidth, render_width);
+  code_list = XtCreateManagedWidget ("code-list", labelWidgetClass,
+                                    code, arg, 3);
   XtInstallAllAccelerators (shell, shell);
 }