*** empty log message ***
authorhanda <handa>
Thu, 10 Jul 2003 13:02:28 +0000 (13:02 +0000)
committerhanda <handa>
Thu, 10 Jul 2003 13:02:28 +0000 (13:02 +0000)
example/otfviewx.c

index 039cb8c..b992e3d 100644 (file)
@@ -7,9 +7,10 @@
 #include <X11/Intrinsic.h>
 #include <X11/StringDefs.h>
 #include <X11/Shell.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Toggle.h>
 #include <X11/Xaw/Box.h>
 #include <X11/Xaw/Form.h>
-#include <X11/Xaw/Command.h>
 #include <X11/Xaw/Viewport.h>
 
 #include <ft2build.h>
@@ -24,32 +25,59 @@ XFontStruct *font;
 
 XtAppContext context;
 /* Widget structure.
-   +---form----------------------------+
-   | +--- command_area --------------+ |
-   | | charmap ...               quit| |
+   +--- frame (form) ------------------+
+   | +--- command_area (box) --------+ |
+   | | quit charmap ...              | |
+   | +-------------------------------+ |
+   | +---- navi_area (box) ----------+ |
    | | PREV prev label next NEXT     | |
    | +-------------------------------+ |
-   | +--- glyph_area ----------------+ |
-   | |                               | |
-   | |                               | |
-   | |                               | |
+   | +--- glyph_area (form) ---------+ |
+   | | glyph[0]     ...    glyph[15] | |
+   | |   ...                 ...     | |
+   | | glyph[112]   ...    glyph[127]| |
    | +-------------------------------+ |
-   | +--- render_area ---------------+ |
-   | | cmap: ...                clear| |
-   | | GSUB: ...                     | |
-   | | GPOS: ...                     | |
+   | +--- render_area (form) --------+ |
+   | | clear                         | |
+   | | +--- raw (box) -------------+ | |
+   | | | raw_label raw_image       | | |
+   | | +--- seq (box) -------------+ | |
+   | | | seq_label seq_image       | | |
+   | | +--- gsub (box) ------------+ | |
+   | | | gsub_label gsub_image     | | |
+   | | +--- gpos (box) ------------+ | |
+   | | | gpos_label gpos_image     | | |
+   | | +---------------------------+ | |
    | +-------------------------------+ |
    +-----------------------------------+ */
-Widget shell, form, command_area, glyph_area, render_area;
-Widget PREV, prev, label, next, NEXT, *charmap, quit, glyph[128], clear;
+Widget shell, frame;
+Widget command_area, quit, *charmap;
+Widget navi_area, PREV, prev, label, next, NEXT;
+Widget glyph_area, glyph[128];
+Widget render_area, clear, raw, seq, gsub, gpos;
+Widget raw_label, raw_image, seq_label, seq_image;
+Widget gsub_label, gsub_image, gpos_label, gpos_image;
 
-unsigned char glyph_exist[0x10000];
-Pixmap pixmap[0x10000];
+int glyph_char[128];
+
+Display *display;
+GC gc, gc_set, gc_or;
+
+typedef struct {
+  Pixmap pixmap;
+  unsigned width, height;
+  int x, y;
+  int advance;
+} BitmapRec;
+
+BitmapRec bitmap[0x10000];
+
+int render_width, render_height;
+Pixmap raw_pixmap, seq_pixmap, gsub_pixmap, gpos_pixmap;
 
 FT_Face face;
 
-struct
-{
+struct {
   int platform_id;
   int encoding_id;
   char name[20];
@@ -61,16 +89,25 @@ unsigned glyph_width, glyph_height;
 int glyph_x, glyph_y;
 int glyph_index;
 
-Pixmap
-create_pixmap (int index, Display *display)
+struct {
+  int n_glyphs;
+  int glyphs[64];
+} glyph_rec;  
+
+OTF *otf;
+
+void
+create_pixmap (int pixel_size, int index)
 {
   int err = FT_Load_Glyph (face, index, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
   XImage ximage;
   Pixmap pixmap;
-  GC gc;
   
   if (err)
-    return (Pixmap) 0;
+    {
+      bitmap[index].pixmap = (Pixmap) 0;
+      return;
+    }
   ximage.height = face->glyph->bitmap.rows;
   ximage.width = face->glyph->bitmap.width;
   ximage.depth = 1;
@@ -86,14 +123,17 @@ create_pixmap (int index, Display *display)
   XInitImage (&ximage);
   pixmap = XCreatePixmap (display, DefaultRootWindow (display),
                          glyph_width, glyph_height, 1);
-  gc = XCreateGC(display, pixmap, (unsigned long) 0, (XGCValues *) 0);
   XFillRectangle (display, pixmap, gc, 0, 0, glyph_width, glyph_height);
   XPutImage (display, pixmap, gc, &ximage, 0, 0,
             glyph_x + face->glyph->bitmap_left,
             glyph_y - face->glyph->bitmap_top,
             ximage.width, ximage.height);
-  XFreeGC (display, gc);
-  return pixmap;
+  bitmap[index].pixmap = pixmap;
+  bitmap[index].width = ximage.width;
+  bitmap[index].height = ximage.height;
+  bitmap[index].x = face->glyph->bitmap_left;
+  bitmap[index].y = - face->glyph->bitmap_top;
+  bitmap[index].advance = face->glyph->metrics.horiAdvance >> 6;
 }
 
 void
@@ -110,25 +150,63 @@ update_glyph_area ()
 
       if (charmap_index >= 0)
        index = FT_Get_Char_Index (face, (FT_ULong) index);
-      XtSetArg (arg[num_args], XtNbitmap, pixmap[index]), num_args++;
-      if (! pixmap[index])
+      XtSetArg (arg[num_args], XtNbitmap, bitmap[index].pixmap), num_args++;
+      if (! bitmap[index].pixmap)
        XtSetArg (arg[num_args], XtNlabel, "none"), num_args++;
       XtSetValues (glyph[i], arg, num_args);
     }
 
-  sprintf (buf, " %04X ", glyph_index);
+  sprintf (buf, " %04X-%04X ", glyph_index, glyph_index + 0x7F);
   XtSetArg (arg[0], XtNlabel, buf);
   XtSetValues (label, arg, 1);
 }
 
 void
+update_render_area ()
+{
+  int i;
+  int x;
+  Arg arg[1];
+
+  XFillRectangle (display, raw_pixmap, gc, 0, 0, render_width, render_height);
+  XFillRectangle (display, seq_pixmap, gc, 0, 0, render_width, render_height);
+  for (i = 0, x = glyph_x; i < glyph_rec.n_glyphs; i++)
+    {
+      BitmapRec *bmp = bitmap + glyph_rec.glyphs[i];
+
+      XCopyArea (display, bmp->pixmap, raw_pixmap, gc,
+                0, 0, glyph_width, glyph_height,
+                (glyph_width + 1) * i + 1, 1);
+      XDrawRectangle (display, raw_pixmap, gc_set,
+                     (glyph_width + 1) * i, 0,
+                     glyph_width + 1, glyph_height + 1);
+      XCopyArea (display, bmp->pixmap, seq_pixmap, gc_or,
+                glyph_x + bmp->x, glyph_y + bmp->y, bmp->width, bmp->height,
+                x + bmp->x, glyph_y + bmp->y);
+      x += bmp->advance;
+    }
+  XtSetArg (arg[0], XtNbitmap, raw_pixmap);
+  XtSetValues (raw_image, arg, 1);
+  XtSetArg (arg[0], XtNbitmap, seq_pixmap);
+  XtSetValues (seq_image, arg, 1);
+  if (! otf)
+    return;
+  XFillRectangle (display, gsub_pixmap, gc, 0, 0, render_width, render_height);
+  XFillRectangle (display, gpos_pixmap, gc, 0, 0, render_width, render_height);
+  XtSetArg (arg[0], XtNbitmap, gsub_pixmap);
+  XtSetValues (gsub_image, arg, 1);
+  XtSetArg (arg[0], XtNbitmap, gpos_pixmap);
+  XtSetValues (gpos_image, arg, 1);
+}
+
+void
 QuitProc (Widget w, XtPointer client_data, XtPointer call_data)
 {
   XtAppSetExitFlag (XtWidgetToApplicationContext (w));
 }
 
 void
-ChangeProc (Widget w, XtPointer client_data, XtPointer call_data)
+GlyphProc (Widget w, XtPointer client_data, XtPointer call_data)
 {
   int old_glyph_index = glyph_index;
 
@@ -145,7 +223,7 @@ ChangeProc (Widget w, XtPointer client_data, XtPointer call_data)
 }
 
 void
-EncodingProc (Widget w, XtPointer client_data, XtPointer call_data)
+CharmapProc (Widget w, XtPointer client_data, XtPointer call_data)
 {
   if (charmap_index == (int) client_data)
     return;
@@ -155,91 +233,109 @@ EncodingProc (Widget w, XtPointer client_data, XtPointer call_data)
   update_glyph_area ();
 }
 
+void
+RenderProc (Widget w, XtPointer client_data, XtPointer call_data)
+{
+  if ((int) client_data < 0)
+    {
+      glyph_rec.n_glyphs = 0;
+      update_render_area ();
+    }
+  else if (glyph_rec.n_glyphs < 64)
+    {
+      int index = glyph_index + (int) client_data;
+      if (charmap_index >= 0)
+       index = FT_Get_Char_Index (face, (FT_ULong) index);
+      glyph_rec.glyphs[glyph_rec.n_glyphs++] = index;
+      update_render_area ();
+    }
+}
 
 void
 create_widgets ()
 {
+  String quit_action = "<KeyPress>q: set() notify() unset()";
   String PREV_action = "Shift<KeyPress>p: set() notify() unset()";
   String prev_action = "~Shift<KeyPress>p: set() notify() unset()";
   String next_action = "~Shift<KeyPress>n: set() notify() unset()";
   String NEXT_action = "Shift<KeyPress>n: set() notify() unset()";
-  String quit_action = "<KeyPress>q: set() notify() unset()";
   Arg arg[10];
   int i, j;
 
-  form = XtCreateManagedWidget ("form", formWidgetClass, shell, NULL, 0);
-  XtSetArg (arg[0], XtNborderWidth, 0);
-  command_area = XtCreateManagedWidget ("command-area", formWidgetClass,
-                                       form, arg, 1);
-  XtSetArg (arg[0], XtNborderWidth, 1);
-  XtSetArg (arg[1], XtNfromVert, command_area);
-  XtSetArg (arg[2], XtNdefaultDistance, 0);
-  glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
-                                     form, arg, 3);
-  XtSetArg (arg[0], XtNborderWidth, 0);
-  XtSetArg (arg[1], XtNfromVert, glyph_area);
-  render_area = XtCreateManagedWidget ("render", formWidgetClass,
-                                      form, arg, 2);
-
-  charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
+  frame = XtCreateManagedWidget ("frame", formWidgetClass, shell, NULL, 0);
   XtSetArg (arg[0], XtNleft, XawChainLeft);
   XtSetArg (arg[1], XtNright, XawChainLeft);
   XtSetArg (arg[2], XtNtop, XawChainTop);
   XtSetArg (arg[3], XtNbottom, XawChainTop);
-  charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, commandWidgetClass,
-                                     command_area, arg, 4);
-  XtAddCallback (charmap[0], XtNcallback, EncodingProc, (XtPointer) -1);
-  for (i = 1; i <= face->num_charmaps; i++)
-    {
-      XtSetArg (arg[4], XtNfromHoriz, charmap[i - 1]);
-      charmap[i] = XtCreateManagedWidget (charmap_rec[i].name,
-                                         commandWidgetClass,
-                                         command_area, arg, 5);
-      XtAddCallback (charmap[i], XtNcallback, EncodingProc,
-                    (XtPointer) (i - 1));
-    }
-  XtSetArg (arg[0], XtNleft, XawChainRight);
-  XtSetArg (arg[1], XtNright, XawChainRight);
-  XtSetArg (arg[4], XtNfromHoriz, charmap[i - 1]);
-  XtSetArg (arg[5], XtNaccelerators, XtParseAcceleratorTable (quit_action));
+  XtSetArg (arg[4], XtNborderWidth, 0);
+  XtSetArg (arg[5], XtNorientation, XtorientHorizontal);
+  command_area = XtCreateManagedWidget ("command-area", boxWidgetClass,
+                                       frame, arg, 6);
+  XtSetArg (arg[6], XtNfromVert, command_area);
+  navi_area = XtCreateManagedWidget ("navi-area", boxWidgetClass,
+                                    frame, arg, 7);
+  XtSetArg (arg[4], XtNborderWidth, 1);
+  XtSetArg (arg[5], XtNfromVert, navi_area);
+  XtSetArg (arg[6], XtNdefaultDistance, 0);
+  glyph_area = XtCreateManagedWidget ("glyph-area", formWidgetClass,
+                                     frame, arg, 7);
+  XtSetArg (arg[4], XtNborderWidth, 0);
+  XtSetArg (arg[5], XtNfromVert, glyph_area);
+  render_area = XtCreateManagedWidget ("render-area", formWidgetClass,
+                                      frame, arg, 6);
+
+  XtSetArg (arg[0], XtNaccelerators, XtParseAcceleratorTable (quit_action));
   quit = XtCreateManagedWidget ("quit", commandWidgetClass,
-                               command_area, arg, 6);
+                               command_area, arg, 1);
   XtAddCallback (quit, XtNcallback, QuitProc, NULL);
 
-  XtSetArg (arg[4], XtNfromVert, charmap[0]);
-  XtSetArg (arg[5], XtNlabel, "<< (P)");
-  XtSetArg (arg[6], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
+  charmap = alloca (sizeof (Widget) * (face->num_charmaps + 1));
+  XtSetArg (arg[0], XtNstate, True);
+  charmap[0] = XtCreateManagedWidget (charmap_rec[0].name, toggleWidgetClass,
+                                     command_area, arg, 1);
+  XtAddCallback (charmap[0], XtNcallback, CharmapProc, (XtPointer) -1);
+  XtSetArg (arg[0], XtNradioGroup, charmap[0]);
+  for (i = 0; i < face->num_charmaps; i++)
+    {
+      charmap[i + 1] = XtCreateManagedWidget (charmap_rec[i + 1].name,
+                                             toggleWidgetClass,
+                                             command_area, arg, 1);
+      XtAddCallback (charmap[i + 1], XtNcallback, CharmapProc, (XtPointer) i);
+    }
+
+  XtSetArg (arg[0], XtNlabel, "<< (P)");
+  XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (PREV_action));
   PREV = XtCreateManagedWidget ("PREV", commandWidgetClass,
-                               command_area, arg, 7);
-  XtAddCallback (PREV, XtNcallback, ChangeProc, (XtPointer) -2);
-  XtSetArg (arg[5], XtNfromHoriz, PREV);
-  XtSetArg (arg[6], XtNlabel, "< (p)");
-  XtSetArg (arg[7], XtNaccelerators, XtParseAcceleratorTable (prev_action));
+                               navi_area, arg, 2);
+  XtAddCallback (PREV, XtNcallback, GlyphProc, (XtPointer) -2);
+  XtSetArg (arg[0], XtNlabel, "< (p)");
+  XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (prev_action));
   prev = XtCreateManagedWidget ("prev", commandWidgetClass,
-                               command_area, arg, 8);
-  XtAddCallback (prev, XtNcallback, ChangeProc, (XtPointer) -1);
-  XtSetArg (arg[5], XtNfromHoriz, prev);
-  XtSetArg (arg[6], XtNlabel, " 0000 ");
+                               navi_area, arg, 2);
+  XtAddCallback (prev, XtNcallback, GlyphProc, (XtPointer) -1);
+  XtSetArg (arg[0], XtNlabel, " 0000 ");
   label = XtCreateManagedWidget ("label", labelWidgetClass,
-                               command_area, arg, 7);
-  XtSetArg (arg[5], XtNfromHoriz, label);
-  XtSetArg (arg[6], XtNlabel, "(n) >");
-  XtSetArg (arg[7], XtNaccelerators, XtParseAcceleratorTable (next_action));
+                                navi_area, arg, 1);
+  XtSetArg (arg[0], XtNlabel, "(n) >");
+  XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (next_action));
   next = XtCreateManagedWidget ("next", commandWidgetClass,
-                               command_area, arg, 8);
-  XtAddCallback (next, XtNcallback, ChangeProc, (XtPointer) 1);
-  XtSetArg (arg[5], XtNfromHoriz, next);
-  XtSetArg (arg[6], XtNlabel, "(N) >>");
-  XtSetArg (arg[7], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
+                               navi_area, arg, 2);
+  XtAddCallback (next, XtNcallback, GlyphProc, (XtPointer) 1);
+  XtSetArg (arg[0], XtNlabel, "(N) >>");
+  XtSetArg (arg[1], XtNaccelerators, XtParseAcceleratorTable (NEXT_action));
   NEXT = XtCreateManagedWidget ("NEXT", commandWidgetClass,
-                               command_area, arg, 8);
-  XtAddCallback (NEXT, XtNcallback, ChangeProc, (XtPointer) 2);
+                               navi_area, arg, 2);
+  XtAddCallback (NEXT, XtNcallback, GlyphProc, (XtPointer) 2);
 
+  XtSetArg (arg[0], XtNleft, XawChainLeft);
+  XtSetArg (arg[1], XtNright, XawChainLeft);
+  XtSetArg (arg[2], XtNtop, XawChainTop);
+  XtSetArg (arg[3], XtNbottom, XawChainTop);
   for (i = 0; i < 8; i++)
     for (j = 0; j < 16; j++)
       {
        int k = i * 16 + j;
-       int num_args = 0;
+       int num_args = 4;
 
        XtSetArg (arg[num_args], XtNwidth, glyph_width), num_args++;
        XtSetArg (arg[num_args], XtNheight, glyph_height), num_args++;
@@ -249,14 +345,64 @@ create_widgets ()
          XtSetArg (arg[num_args], XtNfromVert, glyph[k - 16]), num_args++;
        glyph[k] = XtCreateManagedWidget ("glyph", commandWidgetClass,
                                          glyph_area, arg, num_args);
+       XtAddCallback (glyph[k], XtNcallback, RenderProc, (XtPointer) k);
       }
 
+  XtSetArg (arg[0], XtNleft, XawChainLeft);
+  XtSetArg (arg[1], XtNright, XawChainLeft);
+  XtSetArg (arg[2], XtNtop, XawChainTop);
+  XtSetArg (arg[3], XtNbottom, XawChainTop);
   clear = XtCreateManagedWidget ("clear", commandWidgetClass,
-                                render_area, NULL, 0);
+                                render_area, arg, 4);
+  XtAddCallback (clear, XtNcallback, RenderProc, (XtPointer) -1);
+  XtSetArg (arg[4], XtNorientation, XtorientHorizontal);
+  XtSetArg (arg[5], XtNborderWidth, 0);
+  XtSetArg (arg[6], XtNfromVert, clear);
+  raw = XtCreateManagedWidget ("raw", boxWidgetClass,
+                               render_area, arg, 7);
+  XtSetArg (arg[0], XtNborderWidth, 0);
+  XtSetArg (arg[1], XtNlabel, "raw: ");
+  raw_label = XtCreateManagedWidget ("raw-label", labelWidgetClass,
+                                     raw, arg, 2);
+  XtSetArg (arg[1], XtNbitmap, raw_pixmap);
+  raw_image = XtCreateManagedWidget ("raw-image", labelWidgetClass,
+                                     raw, arg, 2);
+  XtSetArg (arg[6], XtNfromVert, raw);
+  seq = XtCreateManagedWidget ("seq", boxWidgetClass,
+                               render_area, arg, 7);
+  XtSetArg (arg[0], XtNborderWidth, 0);
+  XtSetArg (arg[1], XtNlabel, "seq: ");
+  seq_label = XtCreateManagedWidget ("seq-label", labelWidgetClass,
+                                     seq, arg, 2);
+  XtSetArg (arg[1], XtNbitmap, seq_pixmap);
+  seq_image = XtCreateManagedWidget ("seq-image", labelWidgetClass,
+                                     seq, arg, 2);
+  if (otf)
+    {
+      XtSetArg (arg[6], XtNfromVert, seq);
+      gsub = XtCreateManagedWidget ("gsub", boxWidgetClass,
+                                   render_area, arg, 7);
+      XtSetArg (arg[0], XtNborderWidth, 0);
+      XtSetArg (arg[1], XtNlabel, "gsub: ");
+      gsub_label = XtCreateManagedWidget ("gsub-label", labelWidgetClass,
+                                         gsub, arg, 2);
+      gsub_image = XtCreateManagedWidget ("gsub-image", labelWidgetClass,
+                                         gsub, arg, 1);
+      XtSetArg (arg[6], XtNfromVert, gsub);
+      gpos = XtCreateManagedWidget ("gpos", boxWidgetClass,
+                                   render_area, arg, 7);
+      XtSetArg (arg[0], XtNborderWidth, 0);
+      XtSetArg (arg[1], XtNlabel, "gpos: ");
+      gpos_label = XtCreateManagedWidget ("gpos-label", labelWidgetClass,
+                                         gpos, arg, 2);
+      gpos_image = XtCreateManagedWidget ("gpos-image", labelWidgetClass,
+                                         gpos, arg, 1);
+    }
 
-  XtInstallAllAccelerators (form, form);
+  XtInstallAllAccelerators (frame, frame);
 }
 
+
 /* Format MSG by FMT and print the result to the stderr, and exit.  */
 
 #define FATAL_ERROR(fmt, arg)  \
@@ -268,11 +414,8 @@ create_widgets ()
 int
 main (int argc, char **argv)
 {
-  Display *display;
-
   FT_Library library;
 
-  OTF *otf = NULL;
   OTF_GlyphString gstring;
   OTF_Glyph *g;
 
@@ -299,7 +442,9 @@ main (int argc, char **argv)
       otf = OTF_open (argv[1]);
       if (! otf
          || OTF_get_table (otf, "head") < 0
-         || OTF_get_table (otf, "cmap") < 0)
+         || OTF_get_table (otf, "cmap") < 0
+         || (OTF_get_table (otf, "gsub") < 0
+             && OTF_get_table (otf, "gpos") < 0))
        otf = NULL;
     }
 
@@ -322,7 +467,7 @@ main (int argc, char **argv)
 
   charmap_rec[0].platform_id = -1;
   charmap_rec[0].encoding_id = -1;
-  strcpy (charmap_rec[0].name, "bypass charmap");
+  strcpy (charmap_rec[0].name, "no charmap");
 
   for (i = 0; i < face->num_charmaps; i++)
     {
@@ -339,14 +484,35 @@ main (int argc, char **argv)
        strcat (charmap_rec[i + 1].name, " (apple-roman)");
     }
 
-  for (i = 0; i < 0x10000; i++)
-    pixmap[i] = create_pixmap (i, display);
+  render_width = (glyph_width + 1) * 15 + 1;
+  render_height = glyph_height + 2;
+  raw_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
+                             render_width, render_height, 1);
+  seq_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
+                             render_width, render_height, 1);
+  gsub_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
+                              render_width, render_height, 1);
+  gpos_pixmap = XCreatePixmap (display, DefaultRootWindow (display),
+                              render_width, render_height, 1);
+  {
+    unsigned long valuemask =  GCFunction | GCLineWidth;
+    XGCValues values;
+
+    gc = XCreateGC (display, raw_pixmap, (unsigned long) 0, NULL);
+    values.function = GXset;
+    values.line_width = 1;
+    gc_set = XCreateGC (display, raw_pixmap, valuemask, &values);
+    values.function = GXor;
+    gc_or = XCreateGC (display, raw_pixmap, valuemask, &values);
+  }
 
+  for (i = 0; i < 0x10000; i++)
+    create_pixmap (pixel_size, i);
   create_widgets ();
-
   glyph_index = 0;
   charmap_index = -1;
   update_glyph_area ();
+  update_render_area ();
 
   XtRealizeWidget (shell);
   XtAppMainLoop (context);