From 66440024df88bab9c057b8067a575b66b283376b Mon Sep 17 00:00:00 2001
From: Per Hedbor <ph@opera.com>
Date: Tue, 6 Apr 1999 13:36:07 +0200
Subject: [PATCH] Rewrote parts of the code in C

Rev: lib/modules/_Image_XPM.pmod:1.4
---
 lib/modules/_Image_XPM.pmod | 132 ++++++++++++++++--------------------
 1 file changed, 60 insertions(+), 72 deletions(-)

diff --git a/lib/modules/_Image_XPM.pmod b/lib/modules/_Image_XPM.pmod
index b800de8880..4b377d3d29 100644
--- a/lib/modules/_Image_XPM.pmod
+++ b/lib/modules/_Image_XPM.pmod
@@ -1,68 +1,67 @@
-static mapping parse_color( array color )
-{
-  mapping res = ([]);
-  for(int i=0; i<sizeof(color); i+=2 )
-    if(lower_case(color[i+1]) != "none")
-      res[color[i]] = Colors.parse_color( color[i+1] );
-  return sizeof(res)?res:0;
-}
+inherit Image._XPM;
+#if 0
+#define TE( X )  write("XPM profile: %-20s ... ", (X));
+
+int old_time = gethrtime();
+#define TI() old_time = gethrtime();
+#define TD( X ) do{\
+ write("%3.02f\n", (gethrtime()-old_time)/1000000.0);\
+ TE(X);  \
+ old_time = gethrtime(); \
+} while(0);
+#else
+#define TI()
+#define TD(X)
+#define TE(X)
+#endif
 
-static array find_color( mapping in, string space )
-{
-  if(!in) return 0;
-  switch(space)
-  {
-   default:
-   case "s":
-     if(in->s) return in->s;
-   case "c":
-     if(in->c) return in->c;
-   case "g":
-     if(in->g) return in->g;
-   case "g4":
-     if(in->g4) return in->g4;
-   case "m":
-     if(in->m) return in->m;
-     if(in->s) return in->s;
-  }
-  if(sizeof(in))
-    return values(in)[0];
-  return 0;
-}
 
 mapping _decode( string what, void|mapping opts )
 {
+  array e;
   array data;
   mapping retopts = ([ ]);
   if(!opts)
     opts = ([]);
-  if(sscanf(what, "%*s/*%*[ \t]XPM%*[ \t]*/%*[ \t]\n%s", what)  != 5)
+
+  TE("Scan for header");
+  if(sscanf(what, "%*s/*%*[ \t]XPM%*[ \t]*/%*s{%s", what)  != 5)
     error("This is not a XPM image (1)\n");
-  if(sscanf(what, "%*s{%s", what) != 2)
-    error("This is not a XPM image (2)\n");
 
-  sscanf(what, "%s\n/* XPM */", what ) ||
-    sscanf(what, "%s\n/*\tXPM\t*/", what ) ||
-    sscanf(what, "%s\n/*\tXPM */", what )||
-    sscanf(what, "%s\n/* XPM */", what );
+  if(strlen(what)<100000)
+  {
+    TD("Extra scan for small images");
+    sscanf(what, "%s\n/* XPM */", what ) ||
+      sscanf(what, "%s\n/*\tXPM\t*/", what ) ||
+      sscanf(what, "%s\n/*\tXPM */", what )||
+      sscanf(what, "%s\n/* XPM */", what );
+
+    /* This is just a sanity check... */
+    what = reverse(what);
+    if(sscanf(what, "%*s}%s", what) != 2)
+      error("This is not a XPM image (3)\n");
+    what = reverse(what);
+  }
 
-  what = reverse(what);
-  if(sscanf(what, "%*s}%s", what) != 2)
-    error("This is not a XPM image (3)\n");
-  what = reverse(what);
+  TD("Explode");
+  data = what/"\n";
+  what = 0;
+  int len = sizeof(data);
+  int r, sp;
+
+  TD("Trim");
+  for(int i = 0; i<len; i++)
+    if(strlen(data[i]) &&
+       data[i][0] != '/' && 
+       (sp=search(data[i], "\"")) != -1)
+      data[r++] = (data[i][sp+1..]/"\"")[0];
 
-  
-  master()->set_inhibit_compile_errors(1);
-  if(catch {
-    data = compile_string( "mixed foo(){ return ({"+what+"}); }" )()->foo();
-  })
-    error("This is not a XPM image\n");
-  master()->set_inhibit_compile_errors(0);
-  
   array values = (array(int))(replace(data[0], "\t", " ")/" "-({""}));
-  data = data[1..];
   int width = values[0];
   int height = values[1];
+  if(!width || !height)
+    error("Width or height == 0\n");
+  
   int ncolors = values[2];
   int cpp = values[3];
   if(sizeof(values)>5)
@@ -70,32 +69,21 @@ mapping _decode( string what, void|mapping opts )
     retopts->hot_x = values[4];
     retopts->hot_y = values[5];
   }
-  mapping colors = ([]);
-  for(int i = 0; i<ncolors; i++ )
-  {
-    if(i > sizeof(data))
-      error("Too few elements in array to decode color values\n");
-    string color_id = data[i][0..cpp-1];
-    array color = replace(data[i][cpp..], "\t", " ")/" "-({""});
-    colors[color_id] = parse_color( color );
-  }
-  data = data[ncolors..];
+  TD("Colors");
+  mixed colors = ([]);
+  if(sizeof(data) < ncolors+2)
+    error("Too few elements in array to decode color values\n");
 
+  colors = sort(data[1..ncolors]);
+  TD("Creating images");
   object i = Image.image( width, height );
   object a = Image.image( width, height,255,255,255 );
-
+  mixed cs = opts->colorspace;
+  array c;
+  TD("Decoding image");
   for(int y = 0; y<height && y<sizeof(data); y++)
-  {
-    string line = data[y];
-    for(int x = 0; x<width ; x++)
-    {
-      array c;
-      if( c = find_color(colors[line[x*cpp..x*cpp+cpp-1]], opts->colorspace) )
-        i->setpixel( x, y, @c );
-      else
-        a->setpixel( x, y, 0, 0, 0 );
-    }
-  }
+    _xpm_write_row( y, i, a, data[ncolors+y+1]/cpp, colors );
+  TD("Done");
   retopts->image = i;
   retopts->alpha = a;
   return retopts;
-- 
GitLab