--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "otf.h"
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+FT_Library library;
+FT_Face face;
+
+#include <X11/Xlib.h>
+
+#define FONT_NAME "-adobe-courier-medium-r-normal--12-120-75-75-m-70-iso8859-1"
+#define FONT_HEIGHT 14
+
+Display *display;
+int screen;
+Window win;
+XFontStruct *font;
+GC gc_norm, gc_rev, gc_xor;
+unsigned long valuemask;
+unsigned long foreground, background;
+XGCValues values;
+
+typedef struct
+{
+ int left, top;
+ int rows;
+ int width;
+ int pitch;
+ unsigned char* buf;
+} Bitmap;
+
+Bitmap bitmap[0x10000];
+
+void
+draw_bitmap (int index, int x, int xoff, int width,
+ int y, int yoff, int height, int rev)
+{
+ Bitmap *bmp = bitmap + index;
+ unsigned char *buf = bmp->buf;
+ int i, j;
+ char str[256];
+ int w;
+
+ if (rev)
+ XFillRectangle (display, win, gc_norm, x, y, width, height);
+ XFillRectangle (display, win, gc_xor, x, y + height - FONT_HEIGHT,
+ width, FONT_HEIGHT);
+ XDrawLine (display, win, gc_xor, x, y, x, y + height - 1);
+ sprintf (str, "%04X", index);
+ w = XTextWidth (font, str, 4);
+ XDrawString (display, win, gc_xor, x + (width - w) / 2, y + height - 2,
+ str, 4);
+
+ if (buf)
+ {
+ x += xoff + bmp->left;
+ y += yoff - bmp->top;
+ for (i = 0; i < bmp->rows; i++, buf += bmp->pitch)
+ for (j = 0; j < bmp->width; j++)
+ if (buf[j / 8] & (1 << (7 - (j % 8))))
+ XDrawPoint (display, win, gc_xor, x + j, y + i);
+ }
+}
+
+void
+draw_big_bitmat (int index,
+ int x, int xoff, int width,
+ int y, int yoff, int height)
+{
+ FT_Bitmap *bmp;
+ unsigned char *buf;
+ int i, j;
+
+ FT_Set_Pixel_Sizes (face, 0, 120);
+ if (FT_Load_Glyph (face, index, FT_LOAD_RENDER | FT_LOAD_MONOCHROME))
+ return;
+
+ bmp = &face->glyph->bitmap;
+ buf = bmp->buffer;
+ XFillRectangle (display, win, gc_rev, x, y, width, height);
+ XDrawRectangle (display, win, gc_norm, x - 1, y - 1, width + 1, height + 1);
+ x += xoff + face->glyph->bitmap_left;
+ y += yoff - face->glyph->bitmap_top;
+ for (i = 0; i < bmp->rows; i++, buf += bmp->pitch)
+ for (j = 0; j < bmp->width; j++)
+ if (buf[j / 8] & (1 << (7 - (j % 8))))
+ XDrawPoint (display, win, gc_norm, x + j, y + i);
+}
+
+void
+quit (char *msg)
+{
+ fprintf (stderr, "Error by %s\n", msg);
+ exit (1);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ OTF *otf;
+ int err;
+ int i, max_i, j;
+ int width, height, max_width, max_height;
+ int cols = 16, rows = 8;
+ int x0, y0, x1, y1;
+ int big_height;
+ int first_idx;
+ int left_idx = -1, right_idx = -1;
+ int update_mask;
+#define UPDATE_LEFT 1
+#define UPDATE_RIGHT 2
+#define UPDATE_MAIN 4
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Usage, otfview OTF-FILE");
+ exit (1);
+ }
+
+ otf = otf_open (argv[1]);
+ if (! otf)
+ {
+ otf_perror ("otfview");
+ exit (1);
+ }
+
+ err = FT_Init_FreeType (&library);
+ if (err)
+ quit ("FT_Init_FreeType");
+ err = FT_New_Face (library, argv[1], 0, &face);
+ if (err == FT_Err_Unknown_File_Format)
+ quit ("FT_New_Face: unknown file format");
+ else if (err)
+ quit ("FT_New_Face: unknown error");
+ err = FT_Set_Pixel_Sizes (face, 0, 24);
+ if (err)
+ quit ("FT_Set_Char_Size");
+
+ x0 = x1 = y0 = y1 = 0;
+ for (i = 0; i < 0x10000; i++)
+ {
+ err = FT_Load_Glyph (face, i, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
+ if (err)
+ bitmap[i].buf = NULL;
+ else
+ {
+ Bitmap *bmp = bitmap + i;
+ int bmpsize;
+
+ max_i = i;
+ bmp->left = face->glyph->bitmap_left;
+ bmp->top = face->glyph->bitmap_top;
+ bmp->rows = face->glyph->bitmap.rows;
+ bmp->width = face->glyph->bitmap.width;
+ bmp->pitch = face->glyph->bitmap.pitch;
+ bmpsize = bmp->rows * bmp->pitch;
+ bmp->buf = malloc (bmpsize);
+ memcpy (bmp->buf, face->glyph->bitmap.buffer, bmpsize);
+ if (x0 > bmp->left)
+ x0 = bmp->left;
+ if (y0 > - bmp->top)
+ y0 = - bmp->top;
+ if (x1 < bmp->left + bmp->width)
+ x1 = bmp->left + bmp->width;
+ if (y1 < bmp->rows - bmp->top)
+ y1 = bmp->rows - bmp->top;
+ }
+ }
+
+ max_height = y1 - y0;
+ max_width = x1 - x0;
+
+ display = XOpenDisplay (NULL);
+ screen = DefaultScreen (display);
+
+ big_height = max_height * 5 + 10;
+
+ width = max_width * cols;
+ height = big_height + (max_height + FONT_HEIGHT) * rows;
+
+ win = XCreateSimpleWindow (display, RootWindow (display, screen),
+ 0, 0, width, height, 1,
+ BlackPixel (display, screen),
+ WhitePixel (display, screen));
+
+ font = XLoadQueryFont (display, FONT_NAME);
+ if (! font)
+ font = XLoadQueryFont (display, "fixed");
+ valuemask = GCForeground | GCBackground | GCFunction | GCFont;
+
+ values.foreground = BlackPixel (display, screen);
+ values.background = WhitePixel (display, screen);
+ values.function = GXcopy;
+ values.font = font->fid;
+ gc_norm = XCreateGC (display, win, valuemask, &values);
+
+ values.foreground = WhitePixel (display, screen);
+ values.background = BlackPixel (display, screen);
+ values.function = GXcopy;
+ gc_rev = XCreateGC (display, win, valuemask, &values);
+
+ values.foreground = BlackPixel (display, screen);
+ values.background = WhitePixel (display, screen);
+ values.function = values.foreground ? GXxor : GXequiv;
+ gc_xor = XCreateGC (display, win, valuemask, &values);
+
+ XMapWindow (display, win);
+ XSelectInput (display, win, ExposureMask | KeyPressMask | ButtonPressMask);
+
+ first_idx = 0;
+ update_mask = 0;
+ while (1)
+ {
+ XEvent event;
+
+ XNextEvent (display, &event);
+
+ switch (event.type)
+ {
+ case ButtonPress:
+ {
+ int x = event.xbutton.x;
+ int y = event.xbutton.y;
+
+ if (y < big_height)
+ {
+ if (x < width / 2)
+ {
+ if (first_idx > 0)
+ {
+ first_idx -= cols * rows;
+ update_mask |= UPDATE_MAIN;
+ goto redraw;
+ }
+ }
+ else
+ {
+ if (first_idx + cols * rows <= max_i)
+ {
+ first_idx += cols * rows;
+ update_mask |= UPDATE_MAIN;
+ goto redraw;
+ }
+ }
+ }
+ else
+ {
+ if (event.xbutton.button == Button1)
+ {
+ left_idx = (first_idx
+ + ((y - big_height)
+ / (max_height + FONT_HEIGHT)
+ * cols)
+ + x / max_width);
+ update_mask |= UPDATE_LEFT;
+ }
+ else
+ {
+ right_idx = (first_idx
+ + ((y - big_height)
+ / (max_height + FONT_HEIGHT)
+ * cols)
+ + x / max_width);
+ update_mask |= UPDATE_RIGHT;
+ }
+ goto redraw;
+ }
+ }
+ break;
+
+ case KeyPress:
+ break;
+
+ default:
+ update_mask = UPDATE_LEFT | UPDATE_RIGHT | UPDATE_MAIN;
+ goto redraw;
+ }
+ continue;
+
+ redraw:
+ if (update_mask == (UPDATE_LEFT | UPDATE_RIGHT | UPDATE_MAIN))
+ {
+ XClearWindow (display, win);
+ XDrawLine (display, win, gc_norm, 0, big_height - 1,
+ width, big_height - 1);
+ }
+
+ if (update_mask & UPDATE_MAIN)
+ {
+ XFillRectangle (display, win, gc_rev, 0, big_height, width, height);
+ for (i = 0; i < rows; i++)
+ for (j = 0; j < cols; j++)
+ draw_bitmap (first_idx + i * cols + j,
+ max_width * j, -x0, max_width,
+ big_height + (max_height + FONT_HEIGHT) * i,
+ -y0, max_height + FONT_HEIGHT, 0);
+ }
+ if (update_mask & UPDATE_LEFT)
+ draw_big_bitmat (left_idx, max_width * 2, -x0 * 5, max_width * 5,
+ 5, -y0 * 5, max_height * 5);
+ if (update_mask & UPDATE_RIGHT)
+ draw_big_bitmat (right_idx, max_width * 9, -x0 * 5, max_width * 5,
+ 5, -y0 * 5, max_height * 5);
+ update_mask = 0;
+ }
+
+ otf_close (otf);
+ exit (0);
+}