*** empty log message ***
[m17n/m17n-lib.git] / src / m17n-gd.c
index 3e1ce7a..99269e1 100644 (file)
@@ -1,5 +1,5 @@
 /* m17n-gd.c -- implementation of the GUI API on GD Library.
 /* m17n-gd.c -- implementation of the GUI API on GD Library.
-   Copyright (C) 2004
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
@@ -17,7 +17,7 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the m17n library; if not, write to the Free
 
    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., 59 Temple Place, Suite 330, Boston, MA
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    02111-1307, USA.  */
 
 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
    02111-1307, USA.  */
 
 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
@@ -67,13 +67,39 @@ static MSymbol M_rgb;
 static void
 read_rgb_txt ()
 {
 static void
 read_rgb_txt ()
 {
-  FILE *fp = fopen ("/usr/lib/X11/rgb.txt", "r");
-  int r, g, b;
+  FILE *fp;
+  int r, g, b, i;
+
+  /* At first, support HTML 4.0 color names. */
+  msymbol_put (msymbol ("black"), M_rgb, (void *) 0x000000);
+  msymbol_put (msymbol ("silver"), M_rgb, (void *) 0xC0C0C0);
+  msymbol_put (msymbol ("gray"), M_rgb, (void *) 0x808080);
+  msymbol_put (msymbol ("white"), M_rgb, (void *) 0xFFFFFF);
+  msymbol_put (msymbol ("maroon"), M_rgb, (void *) 0x800000);
+  msymbol_put (msymbol ("red"), M_rgb, (void *) 0xFF0000);
+  msymbol_put (msymbol ("purple"), M_rgb, (void *) 0x800080);
+  msymbol_put (msymbol ("fuchsia"), M_rgb, (void *) 0xFF00FF);
+  msymbol_put (msymbol ("green"), M_rgb, (void *) 0x008000);
+  msymbol_put (msymbol ("lime"), M_rgb, (void *) 0x00FF00);
+  msymbol_put (msymbol ("olive"), M_rgb, (void *) 0x808000);
+  msymbol_put (msymbol ("yellow"), M_rgb, (void *) 0xFFFF00);
+  msymbol_put (msymbol ("navy"), M_rgb, (void *) 0x000080);
+  msymbol_put (msymbol ("blue"), M_rgb, (void *) 0x0000FF);
+  msymbol_put (msymbol ("teal"), M_rgb, (void *) 0x008080);
+  msymbol_put (msymbol ("aqua"), M_rgb, (void *) 0x00FFFF);
 
 
-  if (! fp)
-    fp = fopen ("/usr/X11R6/lib/X11/rgb.txt", "r");
-  if (! fp)
-    return;
+  {
+    char *rgb_path[]
+      =  {"/usr/lib/X11/rgb.txt", "/usr/X11R6/lib/X11/rgb.txt",
+         "/etc/X11/rgb.txt" };
+
+    fp = NULL;
+    for (i = 0; i < (sizeof rgb_path) / (sizeof rgb_path[0]); i++)
+      if ((fp = fopen ("/usr/lib/X11/rgb.txt", "r")))
+       break;
+    if (! fp)
+      return;
+  }
   while (1)
     {
       char buf[256];
   while (1)
     {
       char buf[256];
@@ -95,6 +121,8 @@ read_rgb_txt ()
       buf[0] = c;
       fgets (buf + 1, 255, fp);
       len = strlen (buf);
       buf[0] = c;
       fgets (buf + 1, 255, fp);
       len = strlen (buf);
+      for (i = 0; i < len; i++)
+       buf[i] = tolower (buf[i]);
       if (buf[len - 1] == '\n')
        buf[len - 1] = '\0';
       b |= (r << 16) | (g << 8);
       if (buf[len - 1] == '\n')
        buf[len - 1] = '\0';
       b |= (r << 16) | (g << 8);
@@ -223,6 +251,49 @@ intersect_rectangle (MDrawMetric *r1, MDrawMetric *r2, MDrawMetric *rect)
   gdImageColorResolve ((img), (color) >> 16, ((color) >> 8) & 0xFF,    \
                       (color) & 0xFF)
 
   gdImageColorResolve ((img), (color) >> 16, ((color) >> 8) & 0xFF,    \
                       (color) & 0xFF)
 
+static MRealizedFont *gd_font_open (MFrame *, MFont *, MFont *,
+                                   MRealizedFont *);
+static void gd_render (MDrawWindow, int, int, MGlyphString *,
+                      MGlyph *, MGlyph *, int, MDrawRegion);
+
+static MFontDriver gd_font_driver =
+  { NULL, gd_font_open, NULL, NULL, NULL, gd_render, NULL };
+
+static MRealizedFont *
+gd_font_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
+{
+  double size = font->size ? font->size : spec->size;
+  int reg = spec->property[MFONT_REGISTRY];
+  MRealizedFont *new;
+
+  if (rfont)
+    {
+      MRealizedFont *save = NULL;
+
+      for (; rfont; rfont = rfont->next)
+       if (rfont->font == font
+           && (rfont->font->size ? rfont->font->size == size
+               : rfont->spec.size == size)
+           && rfont->spec.property[MFONT_REGISTRY] == reg)
+         {
+           if (! save)
+             save = rfont;
+           if (rfont->driver == &gd_font_driver)
+             return rfont;
+         }
+      rfont = save;
+    }
+  rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
+  if (! rfont)
+    return NULL;
+  M17N_OBJECT_REF (rfont->info);
+  MSTRUCT_CALLOC (new, MERROR_GD);
+  *new = *rfont;
+  new->driver = &gd_font_driver;
+  new->next = MPLIST_VAL (frame->realized_font_list);
+  MPLIST_VAL (frame->realized_font_list) = new;
+  return new;
+}
 
 static void
 gd_render (MDrawWindow win, int x, int y,
 
 static void
 gd_render (MDrawWindow win, int x, int y,
@@ -230,7 +301,6 @@ gd_render (MDrawWindow win, int x, int y,
           int reverse, MDrawRegion region)
 {
   gdImagePtr img = (gdImagePtr) win;
           int reverse, MDrawRegion region)
 {
   gdImagePtr img = (gdImagePtr) win;
-  MFTInfo *ft_info;
   FT_Face ft_face;
   MRealizedFace *rface = from->rface;
   FT_Int32 load_flags = FT_LOAD_RENDER;
   FT_Face ft_face;
   MRealizedFace *rface = from->rface;
   FT_Int32 load_flags = FT_LOAD_RENDER;
@@ -238,15 +308,12 @@ gd_render (MDrawWindow win, int x, int y,
   int color, pixel;
   int r, g, b;
   
   int color, pixel;
   int r, g, b;
   
-  pixel = RESOLVE_COLOR (img, color);
-
   if (from == to)
     return;
 
   /* It is assured that the all glyphs in the current range use the
      same realized face.  */
   if (from == to)
     return;
 
   /* It is assured that the all glyphs in the current range use the
      same realized face.  */
-  ft_info = (MFTInfo *) rface->rfont->info;
-  ft_face = ft_info->ft_face;
+  ft_face = rface->rfont->fontp;
   color = ((int *) rface->info)[reverse ? COLOR_INVERSE : COLOR_NORMAL];
   pixel = RESOLVE_COLOR (img, color);
 
   color = ((int *) rface->info)[reverse ? COLOR_INVERSE : COLOR_NORMAL];
   pixel = RESOLVE_COLOR (img, color);
 
@@ -261,14 +328,14 @@ gd_render (MDrawWindow win, int x, int y,
 #endif
     }
 
 #endif
     }
 
-  for (; from < to; x += from++->width)
+  for (; from < to; x += from++->g.xadv)
     {
       unsigned char *bmp;
       int xoff, yoff;
       int width, pitch;
 
     {
       unsigned char *bmp;
       int xoff, yoff;
       int width, pitch;
 
-      FT_Load_Glyph (ft_face, (FT_UInt) from->code, load_flags);
-      yoff = y - ft_face->glyph->bitmap_top + from->yoff;
+      FT_Load_Glyph (ft_face, (FT_UInt) from->g.code, load_flags);
+      yoff = y - ft_face->glyph->bitmap_top + from->g.yoff;
       bmp = ft_face->glyph->bitmap.buffer;
       width = ft_face->glyph->bitmap.width;
       pitch = ft_face->glyph->bitmap.pitch;
       bmp = ft_face->glyph->bitmap.buffer;
       width = ft_face->glyph->bitmap.width;
       pitch = ft_face->glyph->bitmap.pitch;
@@ -281,12 +348,18 @@ gd_render (MDrawWindow win, int x, int y,
        for (i = 0; i < ft_face->glyph->bitmap.rows;
             i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
          {
        for (i = 0; i < ft_face->glyph->bitmap.rows;
             i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
          {
-           xoff = x + ft_face->glyph->bitmap_left + from->xoff;
+           xoff = x + ft_face->glyph->bitmap_left + from->g.xoff;
            for (j = 0; j < width; j++, xoff++)
            for (j = 0; j < width; j++, xoff++)
-             if (bmp[j])
+             if (bmp[j] > 0)
                {
                {
-                 int f = bmp[j] >> 5;
                  int pixel1 = pixel;
                  int pixel1 = pixel;
+#if HAVE_GD > 1
+                 int alpha = gdAlphaTransparent * (255 - bmp[j]) / 255;
+
+                 if (alpha > 0)
+                   pixel1 = gdImageColorResolveAlpha (img, r, g, b, alpha);
+#else
+                 int f = bmp[j] >> 5;
 
                  if (f < 7)
                    {
 
                  if (f < 7)
                    {
@@ -301,6 +374,7 @@ gd_render (MDrawWindow win, int x, int y,
                                | ((b * f + b1 * (7 - f)) / 7));
                      pixel1 = RESOLVE_COLOR (img, color1);
                    }
                                | ((b * f + b1 * (7 - f)) / 7));
                      pixel1 = RESOLVE_COLOR (img, color1);
                    }
+#endif
                  gdImageSetPixel (img, xoff, yoff, pixel1);
                }
          }
                  gdImageSetPixel (img, xoff, yoff, pixel1);
                }
          }
@@ -308,7 +382,7 @@ gd_render (MDrawWindow win, int x, int y,
        for (i = 0; i < ft_face->glyph->bitmap.rows;
             i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
          {
        for (i = 0; i < ft_face->glyph->bitmap.rows;
             i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
          {
-           xoff = x + ft_face->glyph->bitmap_left + from->xoff;
+           xoff = x + ft_face->glyph->bitmap_left + from->g.xoff;
            for (j = 0; j < width; j++, xoff++)
              if (bmp[j / 8] & (1 << (7 - (j % 8))))
                gdImageSetPixel (img, xoff, yoff, pixel);
            for (j = 0; j < width; j++, xoff++)
              if (bmp[j / 8] & (1 << (7 - (j % 8))))
                gdImageSetPixel (img, xoff, yoff, pixel);
@@ -316,9 +390,6 @@ gd_render (MDrawWindow win, int x, int y,
     }
 }
 
     }
 }
 
-static MFontDriver gd_font_driver =
-  { NULL, NULL, NULL, NULL, gd_render };
-
 static void
 gd_close (MFrame *frame)
 {
 static void
 gd_close (MFrame *frame)
 {
@@ -443,15 +514,15 @@ gd_draw_empty_boxes (MDrawWindow win, int x, int y,
   y -= gstring->ascent - 1;
   height = gstring->ascent + gstring->descent - 2;
   if (! region)
   y -= gstring->ascent - 1;
   height = gstring->ascent + gstring->descent - 2;
   if (! region)
-    for (; from < to; x += from++->width)
-      gdImageRectangle (img, x, y, x + from->width - 2, y + height - 1, color);
+    for (; from < to; x += from++->g.xadv)
+      gdImageRectangle (img, x, y, x + from->g.xadv - 2, y + height - 1, color);
   else
     {
       gdImagePtr cpy;
       MGlyph *g;
       int width, x1;
 
   else
     {
       gdImagePtr cpy;
       MGlyph *g;
       int width, x1;
 
-      for (g = from, width = 0; g < to; width += g++->width);
+      for (g = from, width = 0; g < to; width += g++->g.xadv);
       cpy = get_scrach_image (img, width, height);
       MPLIST_DO (plist, region_list)
        {
       cpy = get_scrach_image (img, width, height);
       MPLIST_DO (plist, region_list)
        {
@@ -459,8 +530,8 @@ gd_draw_empty_boxes (MDrawWindow win, int x, int y,
          gdImageCopy (cpy, img, rect->x - x, rect->y - y, rect->x, rect->y,
                       rect->x + rect->width, rect->y + rect->height);
        }
          gdImageCopy (cpy, img, rect->x - x, rect->y - y, rect->x, rect->y,
                       rect->x + rect->width, rect->y + rect->height);
        }
-      for (x1 = 0; from < to; x1 += from++->width)
-       gdImageRectangle (cpy, x1, 0, x1 + from->width - 2, height - 1, color);
+      for (x1 = 0; from < to; x1 += from++->g.xadv)
+       gdImageRectangle (cpy, x1, 0, x1 + from->g.xadv - 2, height - 1, color);
       MPLIST_DO (plist, region_list)
        {
          MDrawMetric *rect = MPLIST_VAL (plist);
       MPLIST_DO (plist, region_list)
        {
          MDrawMetric *rect = MPLIST_VAL (plist);
@@ -534,7 +605,7 @@ gd_draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
       gdImagePtr cpy;
 
       if (g->type == GLYPH_BOX)
       gdImagePtr cpy;
 
       if (g->type == GLYPH_BOX)
-       width = g->width;
+       width = g->g.xadv;
       cpy = get_scrach_image (img, width, height);
       MPLIST_DO (plist, region_list)
        {
       cpy = get_scrach_image (img, width, height);
       MPLIST_DO (plist, region_list)
        {
@@ -557,9 +628,9 @@ gd_draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
       int x0, x1;
 
       if (g->left_padding)
       int x0, x1;
 
       if (g->left_padding)
-       x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
+       x0 = x + box->outer_hmargin, x1 = x + g->g.xadv - 1;
       else
       else
-       x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
+       x0 = x, x1 = x + g->g.xadv - box->outer_hmargin - 1;
 
       /* Draw the top side.  */
       color = RESOLVE_COLOR (img, colors[COLOR_BOX_TOP]);
 
       /* Draw the top side.  */
       color = RESOLVE_COLOR (img, colors[COLOR_BOX_TOP]);
@@ -740,9 +811,12 @@ device_init ()
   scratch_images[0] = scratch_images[1] = NULL;
 
   gd_font_driver.select = mfont__ft_driver.select;
   scratch_images[0] = scratch_images[1] = NULL;
 
   gd_font_driver.select = mfont__ft_driver.select;
-  gd_font_driver.open = mfont__ft_driver.open;
   gd_font_driver.find_metric = mfont__ft_driver.find_metric;
   gd_font_driver.find_metric = mfont__ft_driver.find_metric;
+  gd_font_driver.has_char = mfont__ft_driver.has_char;
   gd_font_driver.encode_char = mfont__ft_driver.encode_char;
   gd_font_driver.encode_char = mfont__ft_driver.encode_char;
+  gd_font_driver.list = mfont__ft_driver.list;
+  gd_font_driver.check_otf = mfont__ft_driver.check_otf;
+  gd_font_driver.drive_otf = mfont__ft_driver.drive_otf;
 
   return 0;
 }
 
   return 0;
 }
@@ -766,8 +840,8 @@ device_fini ()
     }
   M17N_OBJECT_UNREF (realized_face_list);
 
     }
   M17N_OBJECT_UNREF (realized_face_list);
 
-  MPLIST_DO (plist, realized_font_list)
-    mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
+  if (MPLIST_VAL (realized_font_list))
+    mfont__free_realized (MPLIST_VAL (realized_font_list));
   M17N_OBJECT_UNREF (realized_font_list);
 
   for (i = 0; i < 2; i++)
   M17N_OBJECT_UNREF (realized_font_list);
 
   for (i = 0; i < 2; i++)
@@ -783,6 +857,9 @@ device_open (MFrame *frame, MPlist *param)
 
   frame->device = NULL;
   frame->device_type = MDEVICE_SUPPORT_OUTPUT;
 
   frame->device = NULL;
   frame->device_type = MDEVICE_SUPPORT_OUTPUT;
+  frame->dpi = (int) mplist_get (param, Mresolution);
+  if (frame->dpi == 0)
+    frame->dpi = 100;
   frame->driver = &gd_driver;
   frame->font_driver_list = mplist ();
   mplist_add (frame->font_driver_list, Mfreetype, &gd_font_driver);
   frame->driver = &gd_driver;
   frame->font_driver_list = mplist ();
   mplist_add (frame->font_driver_list, Mfreetype, &gd_font_driver);
@@ -790,11 +867,17 @@ device_open (MFrame *frame, MPlist *param)
   frame->realized_face_list = realized_face_list;
   frame->realized_fontset_list = realized_fontset_list;
   face = mface_copy (mface__default);
   frame->realized_face_list = realized_face_list;
   frame->realized_fontset_list = realized_fontset_list;
   face = mface_copy (mface__default);
+  mface_put_prop (face, Mfoundry, Mnil);
+  mface_put_prop (face, Mfamily, Mnil);
   mplist_push (param, Mface, face);
   M17N_OBJECT_UNREF (face);
   return 0;
 }
 
   mplist_push (param, Mface, face);
   M17N_OBJECT_UNREF (face);
   return 0;
 }
 
+#else  /* not HAVE_GD nor HAVE_FREETYPE */
+
+int device_open () { return -1; }
+
 #endif /* not HAVE_GD nor HAVE_FREETYPE */
 
 /*** @} */
 #endif /* not HAVE_GD nor HAVE_FREETYPE */
 
 /*** @} */