From b6de2478b77fdf0e973fa52b0c026374bd90c371 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Mon, 19 Jul 1999 01:05:19 -0700
Subject: [PATCH] better error reporting, added some fallbacks for rendering in
 lower resolution if we run out of memory..

Rev: tutorial/Gfx.pmod:1.7
---
 tutorial/Gfx.pmod | 194 +++++++++++++++++++++++++++++-----------------
 1 file changed, 122 insertions(+), 72 deletions(-)

diff --git a/tutorial/Gfx.pmod b/tutorial/Gfx.pmod
index 3d885491b1..45fa5a0835 100644
--- a/tutorial/Gfx.pmod
+++ b/tutorial/Gfx.pmod
@@ -115,93 +115,140 @@ Image.Image errimg=Image.image(10,10)->test();
 mapping read_image(string file, float|void wanted_dpi)
 {
   if(!file) return 0;
-
+  
 //  werror("Reading %s ",file);
   if(file[0]!='_' && srccache[file])
   {
 //    werror("(cached) ");
     return srccache[file];
   }
+  
+  string data=Stdio.read_file(file);
+  if(!data || !strlen(data))
+  {
+    werror("\nFailed to read image %s\n\n",file);
+    return srccache[file]=(["image":errimg]);
+  }
 
-  if( (file/".")[-1]=="fig" )
+  mixed err;
+  
+  switch( (file/".")[-1])
   {
-    Process.create_process(({"fig2dev","-L","ps",file,"___tmp.ps"}))->wait();
-    Stdio.File("___tmp.ps","aw")->write("showpage\n");
-    
-    int res;
-    int scale;
-    switch(wanted_dpi)
+    case "fig":
     {
-      case 0:
-      case 0.0..: scale=3; wanted_dpi=75.0; break;
-      case 10.0..:  scale=5; break;
-      case 50.0..:  scale=3; break;
-      case 150.0..: scale=2; break;
-      case 300.0..: scale=1; break;
-    }
+      int ret=Process.create_process(({"fig2dev","-L","ps",file,"___tmp.ps"}))->wait();
+      
+      if(ret)
+      {
+	werror("\nFig2dev failed with return code %d\n",ret);
+	return (["image":errimg,"dpi":50.0]);
+      }
+      Stdio.File("___tmp.ps","aw")->write("showpage\n");
+      
+      int res;
+      int scale;
+      switch(wanted_dpi)
+      {
+	case 0:
+	case 0.0..: scale=3; wanted_dpi=75.0; break;
+	case 10.0..:  scale=5; break;
+	case 50.0..:  scale=3; break;
+	case 150.0..: scale=2; break;
+	case 300.0..: scale=1; break;
+      }
 
-    res=(int)(scale * wanted_dpi);
-    int maxsize=11*res; // Max size = 11x11 inch
+      object o;
 
-    rm("___tmp.ppm");
-    werror("[rendering at %dx%d dpi] ",(int)wanted_dpi,scale);
+      while(1)
+      {
+	res=(int)(scale * wanted_dpi);
+	int maxsize=11*res; // Max size = 11x11 inch
+	
+	rm("___tmp.ppm");
+	werror("[rendering at %dx%d dpi] ",(int)wanted_dpi,scale);
 #if 0
-    Process.system("/bin/sh -c 'gs -q -sDEVICE=pbmraw -r"+res+" -g"+maxsize+"x"+maxsize+" -sOutputFile=___tmp.ppm ___tmp.ps </dev/null >/dev/null'");
+	Process.system("/bin/sh -c 'gs -q -sDEVICE=pbmraw -r"+res+" -g"+maxsize+"x"+maxsize+" -sOutputFile=___tmp.ppm ___tmp.ps </dev/null >/dev/null'");
 #else
-    int r=Process.create_process(({"gs","-q","-sDEVICE=pbmraw",
-				   "-r"+res,sprintf("-g%dx%d",maxsize,maxsize),
-				   "-sOutputFile=___tmp.ppm","___tmp.ps"}),
-				 (["stdin":Stdio.File("/dev/null","r"),
-				  "stdout":Stdio.File("/dev/null","w")]))->wait();
-
-    if(r)
-    {
-      werror("Gs exited with return code %d.\n",r);
-      exit(1);
-    }
+	int r=Process.create_process(({"gs","-q","-sDEVICE=pbmraw",
+				       "-r"+res,sprintf("-g%dx%d",maxsize,maxsize),
+				       "-sOutputFile=___tmp.ppm","___tmp.ps"}),
+				     (["stdin":Stdio.File("/dev/null","r"),
+				      "stdout":Stdio.File("/dev/null","w")]))->wait();
+	
+	if(r)
+	{
+	  werror("Gs exited with return code %d.\n",r);
+	}
 #endif
-    object o=read_image("___tmp.ppm")->image;
-    m_delete(srccache,"___tmp.ppm");
-    o=o->autocrop()->scale(2.0/3/scale); //->rotate(-90);
-    o=Image.image(o->xsize()+40, o->ysize()+40, PAPER_COLOUR)->paste(o,20,20);
-    rm("___tmp.ps");
-    rm("___tmp.ppm");
-    // Not cached, too big..
-    return (["image":o,"dpi":wanted_dpi]);
-//    if(o!=errimg) srccache[file]=tmp;
-//    return tmp;
-  }
+	o=read_image("___tmp.ppm")->image;
 
-  string data=Stdio.read_file(file);
-  if(!data || !strlen(data))
-  {
-    werror("\nFailed to read image %s\n\n",file);
-    return srccache[file]=(["image":errimg]);
-  }
+	if(o != errimg) break;
+
+	if(o == errimg)
+	{
+	  werror("WARNING: Rendering of %s failed\n",file);
+	  if(scale > 1)
+	  {
+	    werror("Retrying at smaller scale... ");
+	    scale--;
+	  }else{
+	    break;
+	  }
+	}
+      }
+	
+      m_delete(srccache,"___tmp.ppm");
+      o=o->autocrop()->scale(2.0/3/scale); //->rotate(-90);
+      o=Image.image(o->xsize()+40, o->ysize()+40, PAPER_COLOUR)->paste(o,20,20);
+      rm("___tmp.ps");
+      rm("___tmp.ppm");
+      // Not cached, too big..
+      return (["image":o,"dpi":wanted_dpi]);
+    }
+    break;
     
-  catch  {
-    catch {
-      Image.Image i,a;
-      array chunks = Image.GIF._decode( data );
+    case "gif":
+      err=catch  {
+	catch {
+	  Image.Image i,a;
+	  array chunks = Image.GIF._decode( data );
+	  
+	  // If there is more than one render chunk, the image is probably
+	  // an animation. Handling animations is left as an exercise for
+	  // the reader. :-)
+	  foreach(chunks, mixed chunk)
+	    if(arrayp(chunk) && chunk[0] == Image.GIF.RENDER )
+	      [i,a] = chunk[3..4];
+	  if(i) return (["image":i,"alpha":a]);
+	};
+      };
+      break;
       
-      // If there is more than one render chunk, the image is probably
-      // an animation. Handling animations is left as an exercise for
-      // the reader. :-)
-      foreach(chunks, mixed chunk)
-	if(arrayp(chunk) && chunk[0] == Image.GIF.RENDER )
-	  [i,a] = chunk[3..4];
-      if(i) return (["image":i,"alpha":a]);
-    };
-  };
-  catch { return srccache[file]=(["image":Image.JPEG.decode(data)]); };
-  catch  { return srccache[file]=(["image":Image.PNM.decode(data)]); };
-  catch  { return srccache[file]=Image.PNG._decode(data); };
-  werror("\nFailed to decode image %s\n\n",file);
-  return srccache[file]=(["image":errimg]);
-}
+    case "jpg":
+    case "jpeg":
+      err=catch { return srccache[file]=(["image":Image.JPEG.decode(data)]); };
+      break;
+      
+    case "ppm":
+    case "pnm":
+    case "pgm":
+    case "pbm":
+      err=catch  { return srccache[file]=(["image":Image.PNM.decode(data)]); };
+      if(err)
+      {
+	/* possibly out of memory, try again */
+	srccache=([]);
+	gc();
+	err=catch  { return srccache[file]=(["image":Image.PNM.decode(data)]); };
+      }
+      break;
 
-string write_image(string fmt, mapping opts)
-{
+    case "png":
+      err=catch  { return srccache[file]=Image.PNG._decode(data); };
+      break;
+  }
+  werror("\nFailed to decode image %s\n%s\n",file,master()->describe_backtrace(err));
+  return (["image":errimg,"dpi":50.0]);
 }
 
 string gettext(string s)
@@ -214,10 +261,13 @@ string gettext(string s)
 
 array convret(string key,
 	      string ret,
-	      float dpi)
+	      float dpi,
+	      void|object o)
 {
   array tmp=({ret, dpi});
-  illustration_cache[key]=tmp;
+  if(!objectp(o) || !objectp(errimg) || o != errimg)
+    illustration_cache[key]=tmp;
+
   return tmp;
 }
 
@@ -426,7 +476,7 @@ array convert(mapping params,
       if(ret) break;
     }
 
-  return convret(key, ret, o->dpi);
+  return convret(key, ret, o->dpi, o->image);
 }
 
 
-- 
GitLab