/[emacs]/emacs/src/image.c
ViewVC logotype

Diff of /emacs/src/image.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.6.2.3 by miles, Tue May 11 02:38:12 2004 UTC revision 1.6.2.4 by miles, Tue Jul 6 09:14:34 2004 UTC
# Line 3184  xbm_load (f, img) Line 3184  xbm_load (f, img)
3184                                XPM images                                XPM images
3185   ***********************************************************************/   ***********************************************************************/
3186    
3187  #ifdef HAVE_XPM  #if defined (HAVE_XPM) || defined (MAC_OS)
3188    
3189  static int xpm_image_p P_ ((Lisp_Object object));  static int xpm_image_p P_ ((Lisp_Object object));
3190  static int xpm_load P_ ((struct frame *f, struct image *img));  static int xpm_load P_ ((struct frame *f, struct image *img));
3191  static int xpm_valid_color_symbols_p P_ ((Lisp_Object));  static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3192    
3193    #endif /* HAVE_XPM || MAC_OS */
3194    
3195    #ifdef HAVE_XPM
3196  #ifdef HAVE_NTGUI  #ifdef HAVE_NTGUI
3197  /* Indicate to xpm.h that we don't have Xlib.  */  /* Indicate to xpm.h that we don't have Xlib.  */
3198  #define FOR_MSW  #define FOR_MSW
# Line 3208  static int xpm_valid_color_symbols_p P_ Line 3211  static int xpm_valid_color_symbols_p P_
3211  #else  #else
3212  #include "X11/xpm.h"  #include "X11/xpm.h"
3213  #endif /* HAVE_NTGUI */  #endif /* HAVE_NTGUI */
3214    #endif /* HAVE_XPM */
3215    
3216    #if defined (HAVE_XPM) || defined (MAC_OS)
3217  /* The symbol `xpm' identifying XPM-format images.  */  /* The symbol `xpm' identifying XPM-format images.  */
3218    
3219  Lisp_Object Qxpm;  Lisp_Object Qxpm;
# Line 3536  xpm_image_p (object) Line 3541  xpm_image_p (object)
3541                || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));                || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
3542  }  }
3543    
3544    #endif /* HAVE_XPM || MAC_OS */
3545    
3546  /* Load image IMG which will be displayed on frame F.  Value is  /* Load image IMG which will be displayed on frame F.  Value is
3547     non-zero if successful.  */     non-zero if successful.  */
3548    
3549    #ifdef HAVE_XPM
3550    
3551  static int  static int
3552  xpm_load (f, img)  xpm_load (f, img)
3553       struct frame *f;       struct frame *f;
# Line 3771  xpm_load (f, img) Line 3779  xpm_load (f, img)
3779    
3780  #endif /* HAVE_XPM */  #endif /* HAVE_XPM */
3781    
3782    #ifdef MAC_OS
3783    
3784    /* XPM support functions for Mac OS where libxpm is not available.
3785       Only XPM version 3 (without any extensions) is supported.  */
3786    
3787    static int xpm_scan P_ ((unsigned char **, unsigned char *,
3788                           unsigned char **, int *));
3789    static Lisp_Object xpm_make_color_table_v
3790      P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
3791           Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
3792    static void xpm_put_color_table_v P_ ((Lisp_Object, unsigned char *,
3793                                         int, Lisp_Object));
3794    static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
3795                                                unsigned char *, int));
3796    static Lisp_Object xpm_make_color_table_h
3797      P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
3798           Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
3799    static void xpm_put_color_table_h P_ ((Lisp_Object, unsigned char *,
3800                                         int, Lisp_Object));
3801    static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
3802                                                unsigned char *, int));
3803    static int xpm_str_to_color_key P_ ((char *));
3804    static int xpm_load_image P_ ((struct frame *, struct image *,
3805                                 unsigned char *, unsigned char *));
3806    
3807    /* Tokens returned from xpm_scan.  */
3808    
3809    enum xpm_token
3810    {
3811      XPM_TK_IDENT = 256,
3812      XPM_TK_STRING,
3813      XPM_TK_EOF
3814    };
3815    
3816    /* Scan an XPM data and return a character (< 256) or a token defined
3817       by enum xpm_token above.  *S and END are the start (inclusive) and
3818       the end (exclusive) addresses of the data, respectively.  Advance
3819       *S while scanning.  If token is either XPM_TK_IDENT or
3820       XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3821       length of the corresponding token, respectively.  */
3822    
3823    static int
3824    xpm_scan (s, end, beg, len)
3825         unsigned char **s, *end, **beg;
3826         int *len;
3827    {
3828      int c;
3829    
3830      while (*s < end)
3831        {
3832          /* Skip white-space.  */
3833          while (*s < end && (c = *(*s)++, isspace (c)))
3834          ;
3835    
3836          /* gnus-pointer.xpm uses '-' in its identifier.
3837           sb-dir-plus.xpm uses '+' in its identifier.  */
3838          if (isalpha (c) || c == '_' || c == '-' || c == '+')
3839          {
3840            *beg = *s - 1;
3841            while (*s < end &&
3842                   (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
3843                ++*s;
3844            *len = *s - *beg;
3845            return XPM_TK_IDENT;
3846          }
3847          else if (c == '"')
3848          {
3849            *beg = *s;
3850            while (*s < end && **s != '"')
3851              ++*s;
3852            *len = *s - *beg;
3853            if (*s < end)
3854              ++*s;
3855            return XPM_TK_STRING;
3856          }
3857          else if (c == '/')
3858          {
3859            if (*s < end && **s == '*')
3860              {
3861                /* C-style comment.  */
3862                ++*s;
3863                do
3864                  {
3865                    while (*s < end && *(*s)++ != '*')
3866                      ;
3867                  }
3868                while (*s < end && **s != '/');
3869                if (*s < end)
3870                  ++*s;
3871              }
3872            else
3873              return c;
3874          }
3875          else
3876          return c;
3877        }
3878    
3879      return XPM_TK_EOF;
3880    }
3881    
3882    /* Functions for color table lookup in XPM data.  A Key is a string
3883       specifying the color of each pixel in XPM data.  A value is either
3884       an integer that specifies a pixel color, Qt that specifies
3885       transparency, or Qnil for the unspecified color.  If the length of
3886       the key string is one, a vector is used as a table.  Otherwise, a
3887       hash table is used.  */
3888    
3889    static Lisp_Object
3890    xpm_make_color_table_v (put_func, get_func)
3891         void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
3892         Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
3893    {
3894      *put_func = xpm_put_color_table_v;
3895      *get_func = xpm_get_color_table_v;
3896      return Fmake_vector (make_number (256), Qnil);
3897    }
3898    
3899    static void
3900    xpm_put_color_table_v (color_table, chars_start, chars_len, color)
3901         Lisp_Object color_table;
3902         unsigned char *chars_start;
3903         int chars_len;
3904         Lisp_Object color;
3905    {
3906      XVECTOR (color_table)->contents[*chars_start] = color;
3907    }
3908    
3909    static Lisp_Object
3910    xpm_get_color_table_v (color_table, chars_start, chars_len)
3911         Lisp_Object color_table;
3912         unsigned char *chars_start;
3913         int chars_len;
3914    {
3915      return XVECTOR (color_table)->contents[*chars_start];
3916    }
3917    
3918    static Lisp_Object
3919    xpm_make_color_table_h (put_func, get_func)
3920         void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
3921         Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
3922    {
3923      *put_func = xpm_put_color_table_h;
3924      *get_func = xpm_get_color_table_h;
3925      return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
3926                            make_float (DEFAULT_REHASH_SIZE),
3927                            make_float (DEFAULT_REHASH_THRESHOLD),
3928                            Qnil, Qnil, Qnil);
3929    }
3930    
3931    static void
3932    xpm_put_color_table_h (color_table, chars_start, chars_len, color)
3933         Lisp_Object color_table;
3934         unsigned char *chars_start;
3935         int chars_len;
3936         Lisp_Object color;
3937    {
3938      struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
3939      unsigned hash_code;
3940      Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
3941    
3942      hash_lookup (table, chars, &hash_code);
3943      hash_put (table, chars, color, hash_code);
3944    }
3945    
3946    static Lisp_Object
3947    xpm_get_color_table_h (color_table, chars_start, chars_len)
3948         Lisp_Object color_table;
3949         unsigned char *chars_start;
3950         int chars_len;
3951    {
3952      struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
3953      int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
3954                         NULL);
3955    
3956      return i >= 0 ? HASH_VALUE (table, i) : Qnil;
3957    }
3958    
3959    enum xpm_color_key {
3960      XPM_COLOR_KEY_S,
3961      XPM_COLOR_KEY_M,
3962      XPM_COLOR_KEY_G4,
3963      XPM_COLOR_KEY_G,
3964      XPM_COLOR_KEY_C
3965    };
3966    
3967    static char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
3968    
3969    static int
3970    xpm_str_to_color_key (s)
3971         char *s;
3972    {
3973      int i;
3974    
3975      for (i = 0;
3976           i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
3977           i++)
3978        if (strcmp (xpm_color_key_strings[i], s) == 0)
3979          return i;
3980      return -1;
3981    }
3982    
3983    static int
3984    xpm_load_image (f, img, contents, end)
3985         struct frame *f;
3986         struct image *img;
3987         unsigned char *contents, *end;
3988    {
3989      unsigned char *s = contents, *beg, *str;
3990      unsigned char buffer[BUFSIZ];
3991      int width, height, x, y;
3992      int num_colors, chars_per_pixel;
3993      int len, LA1;
3994      void (*put_color_table) (Lisp_Object, unsigned char *, int, Lisp_Object);
3995      Lisp_Object (*get_color_table) (Lisp_Object, unsigned char *, int);
3996      Lisp_Object frame, color_symbols, color_table;
3997      int best_key, have_mask = 0;
3998      XImagePtr ximg = NULL, mask_img = NULL;
3999    
4000    #define match() \
4001         LA1 = xpm_scan (&s, end, &beg, &len)
4002    
4003    #define expect(TOKEN)         \
4004         if (LA1 != (TOKEN))      \
4005           goto failure;          \
4006         else                     \
4007           match ()
4008    
4009    #define expect_ident(IDENT)                                   \
4010         if (LA1 == XPM_TK_IDENT \
4011             && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0)  \
4012            match ();                                              \
4013         else                                                     \
4014           goto failure
4015    
4016      if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
4017        goto failure;
4018      s += 9;
4019      match();
4020      expect_ident ("static");
4021      expect_ident ("char");
4022      expect ('*');
4023      expect (XPM_TK_IDENT);
4024      expect ('[');
4025      expect (']');
4026      expect ('=');
4027      expect ('{');
4028      expect (XPM_TK_STRING);
4029      if (len >= BUFSIZ)
4030        goto failure;
4031      memcpy (buffer, beg, len);
4032      buffer[len] = '\0';
4033      if (sscanf (buffer, "%d %d %d %d", &width, &height,
4034                &num_colors, &chars_per_pixel) != 4
4035          || width <= 0 || height <= 0
4036          || num_colors <= 0 || chars_per_pixel <= 0)
4037        goto failure;
4038      expect (',');
4039    
4040      XSETFRAME (frame, f);
4041      if (!NILP (Fxw_display_color_p (frame)))
4042        best_key = XPM_COLOR_KEY_C;
4043      else if (!NILP (Fx_display_grayscale_p (frame)))
4044        best_key = (XFASTINT (Fx_display_planes (frame)) > 2
4045                  ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
4046      else
4047        best_key = XPM_COLOR_KEY_M;
4048    
4049      color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4050      if (chars_per_pixel == 1)
4051        color_table = xpm_make_color_table_v (&put_color_table,
4052                                            &get_color_table);
4053      else
4054        color_table = xpm_make_color_table_h (&put_color_table,
4055                                            &get_color_table);
4056    
4057      while (num_colors-- > 0)
4058        {
4059          unsigned char *color, *max_color;
4060          int key, next_key, max_key = 0;
4061          Lisp_Object symbol_color = Qnil, color_val;
4062          XColor cdef;
4063    
4064          expect (XPM_TK_STRING);
4065          if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
4066          goto failure;
4067          memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
4068          buffer[len - chars_per_pixel] = '\0';
4069    
4070          str = strtok (buffer, " \t");
4071          if (str == NULL)
4072          goto failure;
4073          key = xpm_str_to_color_key (str);
4074          if (key < 0)
4075          goto failure;
4076          do
4077          {
4078            color = strtok (NULL, " \t");
4079            if (color == NULL)
4080              goto failure;
4081    
4082            while (str = strtok (NULL, " \t"))
4083              {
4084                next_key = xpm_str_to_color_key (str);
4085                if (next_key >= 0)
4086                  break;
4087                color[strlen (color)] = ' ';
4088              }
4089    
4090            if (key == XPM_COLOR_KEY_S)
4091              {
4092                if (NILP (symbol_color))
4093                  symbol_color = build_string (color);
4094              }
4095            else if (max_key < key && key <= best_key)
4096              {
4097                max_key = key;
4098                max_color = color;
4099              }
4100            key = next_key;
4101          }
4102          while (str);
4103    
4104          color_val = Qnil;
4105          if (!NILP (color_symbols) && !NILP (symbol_color))
4106          {
4107            Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
4108    
4109            if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
4110              if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
4111                color_val = Qt;
4112              else if (x_defined_color (f, SDATA (XCDR (specified_color)),
4113                                        &cdef, 0))
4114                color_val = make_number (cdef.pixel);
4115          }
4116          if (NILP (color_val) && max_key > 0)
4117          if (xstricmp (max_color, "None") == 0)
4118            color_val = Qt;
4119          else if (x_defined_color (f, max_color, &cdef, 0))
4120            color_val = make_number (cdef.pixel);
4121          if (!NILP (color_val))
4122          (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
4123    
4124          expect (',');
4125        }
4126    
4127      if (!x_create_x_image_and_pixmap (f, width, height, 0,
4128                                      &ximg, &img->pixmap)
4129          || !x_create_x_image_and_pixmap (f, width, height, 1,
4130                                         &mask_img, &img->mask))
4131        {
4132          image_error ("Out of memory (%s)", img->spec, Qnil);
4133          goto error;
4134        }
4135    
4136      for (y = 0; y < height; y++)
4137        {
4138          expect (XPM_TK_STRING);
4139          str = beg;
4140          if (len < width * chars_per_pixel)
4141          goto failure;
4142          for (x = 0; x < width; x++, str += chars_per_pixel)
4143          {
4144            Lisp_Object color_val =
4145              (*get_color_table) (color_table, str, chars_per_pixel);
4146    
4147            XPutPixel (ximg, x, y,
4148                       (INTEGERP (color_val) ? XINT (color_val)
4149                        : FRAME_FOREGROUND_PIXEL (f)));
4150            XPutPixel (mask_img, x, y,
4151                       (!EQ (color_val, Qt) ? PIX_MASK_DRAW (f)
4152                        : (have_mask = 1, PIX_MASK_RETAIN (f))));
4153          }
4154          if (y + 1 < height)
4155          expect (',');
4156        }
4157    
4158      img->width = width;
4159      img->height = height;
4160    
4161      x_put_x_image (f, ximg, img->pixmap, width, height);
4162      x_destroy_x_image (ximg);
4163      if (have_mask)
4164        {
4165          x_put_x_image (f, mask_img, img->mask, width, height);
4166          x_destroy_x_image (mask_img);
4167        }
4168      else
4169        {
4170          x_destroy_x_image (mask_img);
4171          Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4172          img->mask = NO_PIXMAP;
4173        }
4174    
4175      return 1;
4176    
4177     failure:
4178      image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4179     error:
4180      x_destroy_x_image (ximg);
4181      x_destroy_x_image (mask_img);
4182      x_clear_image (f, img);
4183      return 0;
4184    
4185    #undef match
4186    #undef expect
4187    #undef expect_ident
4188    }
4189    
4190    static int
4191    xpm_load (f, img)
4192         struct frame *f;
4193         struct image *img;
4194    {
4195      int success_p = 0;
4196      Lisp_Object file_name;
4197    
4198      /* If IMG->spec specifies a file name, create a non-file spec from it.  */
4199      file_name = image_spec_value (img->spec, QCfile, NULL);
4200      if (STRINGP (file_name))
4201        {
4202          Lisp_Object file;
4203          unsigned char *contents;
4204          int size;
4205          struct gcpro gcpro1;
4206    
4207          file = x_find_image_file (file_name);
4208          GCPRO1 (file);
4209          if (!STRINGP (file))
4210          {
4211            image_error ("Cannot find image file `%s'", file_name, Qnil);
4212            UNGCPRO;
4213            return 0;
4214          }
4215    
4216          contents = slurp_file (SDATA (file), &size);
4217          if (contents == NULL)
4218          {
4219            image_error ("Error loading XPM image `%s'", img->spec, Qnil);
4220            UNGCPRO;
4221            return 0;
4222          }
4223    
4224          success_p = xpm_load_image (f, img, contents, contents + size);
4225          xfree (contents);
4226          UNGCPRO;
4227        }
4228      else
4229        {
4230          Lisp_Object data;
4231    
4232          data = image_spec_value (img->spec, QCdata, NULL);
4233          success_p = xpm_load_image (f, img, SDATA (data),
4234                                    SDATA (data) + SBYTES (data));
4235        }
4236    
4237      return success_p;
4238    }
4239    
4240    #endif /* MAC_OS */
4241    
4242    
4243    
4244  /***********************************************************************  /***********************************************************************
4245                               Color table                               Color table
# Line 7447  syms_of_image () Line 7916  syms_of_image ()
7916    Qxbm = intern ("xbm");    Qxbm = intern ("xbm");
7917    staticpro (&Qxbm);    staticpro (&Qxbm);
7918    
7919  #ifdef HAVE_XPM  #if defined (HAVE_XPM) || defined (MAC_OS)
7920    Qxpm = intern ("xpm");    Qxpm = intern ("xpm");
7921    staticpro (&Qxpm);    staticpro (&Qxpm);
7922  #endif  #endif
# Line 7517  init_image () Line 7986  init_image ()
7986    define_image_type (&xbm_type);    define_image_type (&xbm_type);
7987    define_image_type (&pbm_type);    define_image_type (&pbm_type);
7988    
7989  #ifdef HAVE_XPM  #if defined (HAVE_XPM) || defined (MAC_OS)
7990    IF_LIB_AVAILABLE(init_xpm_functions)    IF_LIB_AVAILABLE(init_xpm_functions)
7991      define_image_type (&xpm_type);      define_image_type (&xpm_type);
7992  #endif  #endif

Legend:
Removed from v.1.6.2.3  
changed lines
  Added in v.1.6.2.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26