[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-user: PCB: some stupid thoughts on PNG output



Once I thought what if PCB would generate a directory
of PNG files, every file highlighting if's own element.
this might be convenient in some cases when mounting them
on the board. I see, usually people who do this either
have no terminal at all or have PCB installed and may
just run it; and those files may fill too many bytes;
however, there may be some cases when it could be useful.

So I vim:

#! /bin/bash
if test $# -lt 1 ; then
# $1 shall be the name of the file to process
   exit 1;
fi
rm -fr highlighted;mkdir highlighted
dpi=180
if test "z$DPI" != z ; then
  dpi=$DPI
fi
rm pcb-script
photo=--as-shown
if test "z$PHOTO_MODE" != z ; then
  photo=--photo-mode
fi
case $photo in
  --photo-mode)
    # '#00ffff' will be hardcoded
    # as color of selected objects for photo-mode
    selected='#00ffff'
    ;;
  *)
    #highlight them with red
    selected='#ff0000'
    #OSDCU.pcb has four copper layers;
    # I want only component or solder
    for i in `seq 1 4`;do
      echo "ChangeGroupVisibility($i)" >>pcb-script
    done
    ;;
esac
grep '^Element[[]""' $1|\
  sed 's/Element[[]"" "[^"]*" "\([^"]*\).*/\1/'\
    |while read i; do
  echo "Select(ElementByName,$i)" >>pcb-script
  echo -n "    RunExporter(png,$photo,--dpi,$dpi," >>pcb-script
  echo "--outfile,highlighted/$i.png)" >>pcb-script
  echo "Undo()" >>pcb-script
 done
case $photo in
  --photo-mode) ;;
  *) echo "SwapSides()" >>pcb-script ;;
esac
grep '^Element[[]"onsolder"' $1|\
 sed 's/Element[[]"onsolder" "[^"]*" "\([^"]*\).*/\1/'\
 |while read i; do
  echo "Select(ElementByName,$i)" >>pcb-script
  echo -n "    RunExporter(png,$photo," >>pcb-script
  echo -n "--dpi,$dpi,--photo-flip-y," >>pcb-script
  echo "--outfile,highlighted/$i-onsolder.png)" >>pcb-script
  echo "Undo()" >>pcb-script
 done
echo 'q!' >>pcb-script
pcb --layer-color-1 '#618B8B' --layer-color-2 '#618B8B'\
 --layer-selected-color-1 ${selected}\
 --layer-selected-color-2 ${selected}\
 --pin-selected-color ${selected} \
 --element-selected-color ${selected}\
 --action-script pcb-script $1
rm pcb-script

Hmm. batch HID has no SwapSides action; GUI HIDs need X to
run scripts, and I typically don't launch ratpoison unless
I really need a graphical terminal.

[0001-add-SwapSides-action-to-batch-HID.patch]

Then, there seems to be no way to invoke exporter
non-interactively from such scripts, and I'll want to disable
layers on more-than-single-layer boards.

[0002-add-RunExporter-and-ChangeGroupVisibility-actions.patch]

Now, --as-shown is essentially enough, but I'll need to
mirror solder-side images externally after that.

[0003-extend-photo-flip-options-to-non-photo-mode.patch]

Ah, and selected objects are not honoured in photo mode.

[0004-distinguish-selected-objects-in-photo-mode.patch]

Actually, the last patch deals with one more issue:
I observed that the exporter pours memory, especially when in
photo mode. I saw with my own eyes more than 100 MB per MB of
output images at a reasonably high --dpi. isn't it admirable?

It is OK when the exporter is invoked several times per run,
but I had to close widest of those apertures in order
to produce images in industrial quantities on my poor machines.
of course, I can run pcb N times instead of exporting all in single
run,  but this might be significantly slower at lower resolutions.

Any other ideas?
From 40fd8668760e01003917de9fd5d3e75b05f09ca0 Mon Sep 17 00:00:00 2001
From: Ineiev <ineiev@xxxxxxxxxxxxxxxx>
Date: Sun, 21 Jun 2009 07:01:00 +0000
Subject: [PATCH 1/4] add SwapSides action to batch HID

---
 ChangeLog             |    4 ++
 src/hid/batch/batch.c |   86 ++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 86 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index cd22fb5..40035eb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-06-21 17:17  ineiev
+
+	* src/hid/batch/batch.c: add SwapSides action
+
 2009-05-17 15:17  jaredcasper
 
 	* configure.ac,src/hid/lpr/hid.conf: Added top level check for
diff --git a/src/hid/batch/batch.c b/src/hid/batch/batch.c
index 171926b..f5c1cac 100644
--- a/src/hid/batch/batch.c
+++ b/src/hid/batch/batch.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -12,13 +10,12 @@
 #include "global.h"
 #include "hid.h"
 #include "data.h"
+#include "misc.h"
 
 #ifdef HAVE_LIBDMALLOC
 #include <dmalloc.h>
 #endif
 
-RCSID ("$Id$");
-
 /* This is a text-line "batch" HID, which exists for scripting and
    non-GUI needs.  */
 
@@ -96,6 +93,85 @@ info (int argc, char **argv, int x, int y)
   return 0;
 }
 
+/* ---------------------------------------------------------------------- */
+static const char swapsides_syntax[] =
+"SwapSides(|v|h|r)";
+
+static const char swapsides_help[] =
+"Swaps the side of the board you're looking at.";
+
+/* %start-doc actions SwapSides
+
+This action shows the opposite side of the board.
+
+Normally, this action changes which pads and silk layer are drawn as
+true silk, and which are drawn as the "invisible" layer.  It also
+determines which solder mask you see.
+
+As a special case, if the layer group for the side you're looking at
+is visible and currently active, and the layer group for the opposite
+is not visible (i.e. disabled), then this action will also swap which
+layer group is visible and active, effectively swapping the ``working
+side'' of the board.
+
+%end-doc */
+
+
+static int
+SwapSides (int argc, char **argv, int x, int y)
+{
+  int comp_group = GetLayerGroupNumberByNumber (max_layer + COMPONENT_LAYER);
+  int solder_group = GetLayerGroupNumberByNumber (max_layer + SOLDER_LAYER);
+  int active_group = GetLayerGroupNumberByNumber (LayerStack[0]);
+  int comp_showing =
+    PCB->Data->Layer[PCB->LayerGroups.Entries[comp_group][0]].On;
+  int solder_showing =
+    PCB->Data->Layer[PCB->LayerGroups.Entries[solder_group][0]].On;
+
+
+  if (argc > 0)
+    {
+     /* basic arguments handling for compatibility with GTK and Lesstif HIDs */
+      switch (argv[0][0]) {
+      case 'h':
+      case 'H':
+	break;
+      case 'v':
+      case 'V':
+	break;
+      case 'r':
+      case 'R':
+	break;
+      default:
+	return 1;
+      }
+    }
+
+  Settings.ShowSolderSide = !Settings.ShowSolderSide;
+  if (Settings.ShowSolderSide)
+    {
+      if (active_group == comp_group && comp_showing && !solder_showing)
+	{
+	  ChangeGroupVisibility (PCB->LayerGroups.Entries[comp_group][0], 0,
+				 0);
+	  ChangeGroupVisibility (PCB->LayerGroups.Entries[solder_group][0], 1,
+				 1);
+	}
+    }
+  else
+    {
+      if (active_group == solder_group && solder_showing && !comp_showing)
+	{
+	  ChangeGroupVisibility (PCB->LayerGroups.Entries[solder_group][0], 0,
+				 0);
+	  ChangeGroupVisibility (PCB->LayerGroups.Entries[comp_group][0], 1,
+				 1);
+	}
+    }
+
+  return 0;
+}
+
 
 HID_Action batch_action_list[] = {
   {"PCBChanged", 0, PCBChanged },
@@ -105,6 +181,8 @@ HID_Action batch_action_list[] = {
   {"LibraryChanged", 0, nop },
   {"Busy", 0, nop },
   {"Help", 0, help },
+  {"SwapSides", 0, SwapSides,
+   swapsides_help, swapsides_syntax},
   {"Info", 0, info }
 };
 
-- 
1.6.2.4

From 2d70efd363761299b3eb6a1ca4e53f02c6ce7f6a Mon Sep 17 00:00:00 2001
From: Ineiev <ineiev@xxxxxxxxxxxxxxxx>
Date: Sun, 21 Jun 2009 06:12:04 +0000
Subject: [PATCH 2/4] add RunExporter and ChangeGroupVisibility actions

RunExporter action invokes an exporter without further user input.
This action provides functinality of
-x command line option in PCB action scripts.

example: RunExporter(png,--outfile,out.png,--photo-mode)

ChangeGroupVisibility is just a handle to the function defined in misc.c
---
 ChangeLog    |    4 ++
 src/action.c |   87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 90 insertions(+), 1 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 40035eb..8634bdc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2009-06-21 17:17  ineiev
 
+	* src/action.c: add RunExporter and ChangeGroupVisibility actions
+
+2009-06-21 17:17  ineiev
+
 	* src/hid/batch/batch.c: add SwapSides action
 
 2009-05-17 15:17  jaredcasper
diff --git a/src/action.c b/src/action.c
index ce7527f..a399c4b 100644
--- a/src/action.c
+++ b/src/action.c
@@ -1,5 +1,4 @@
 /* $Id$ */
-/* 15 Oct 2008 Ineiev: add CycleCrosshair action */
 
 /*
  *                            COPYRIGHT
@@ -5113,6 +5112,51 @@ ActionClearOctagon (int argc, char **argv, int x, int y)
 }
 
 /* --------------------------------------------------------------------------- */
+/* %start-doc actions ChangeGroupVisibility
+ *
+ * Change the visibility of all layers in a group
+ *
+ * @table @code
+ *
+ * @item group_number
+ * Number of the group to operate on.
+ *
+ * @item visible
+ * Whether to show or hide the group.
+ *
+ * @item change_stack
+ * Whether to change layer stack.
+ *
+ * @end table
+ *
+ * @example
+ * ChangeGroupVisibility(1,on,off)
+ * @end example
+ *
+ * %end-doc */
+static const char change_group_visibility_syntax[] =
+  "ChangeGroupVisibility(group_number,visible,change_stack)\n";
+
+static const char change_group_visibility_help[] =
+ "Changes visibility of layers in a group.\n"
+ "   visible = on | off\n"
+ "   change_stack = on | off\n";
+
+static int
+ActionGroupVisibility (int argc, char **argv, int x, int y)
+{
+  int layer = argc > 0 ? atoi (argv[0]) : 0;
+  int on=0, change_order=0;
+
+  if (argc>1 && !strcmp (argv[1], "on"))
+    on = 1;
+  if (argc>2 && !strcmp (argv[2], "on"))
+    change_order = 1;
+  ChangeGroupVisibility (layer, on, change_order);
+  return 0;
+}
+
+/* --------------------------------------------------------------------------- */
 
 static const char changehold_syntax[] =
   "ChangeHole(ToggleObject|Object|SelectedVias|Selected)";
@@ -6794,6 +6838,41 @@ ActionPSCalib (int argc, char **argv, int x, int y)
 }
 
 /* --------------------------------------------------------------------------- */
+/* %start-doc actions RunExporter
+
+Invoke an exporter without further user input.
+This action provides functinality of
+@code{-x} command line option in PCB action scripts.
+
+@example
+RunExporter(png,--outfile,out.png,--photo-mode)
+@end example
+
+%end-doc */
+static const char run_exporter_syntax[] =
+  "RunExporter(HID[,option...])\n";
+
+static const char run_exporter_help[] = "Invokes an exporter.";
+
+static int
+RunExporter (int argc, char **argv, int x, int y)
+{
+  HID *exporter;
+
+  if(argc<1)
+    AFAIL(run_exporter);
+
+  exporter = hid_find_exporter (argv[0]);
+
+  if(NULL == exporter)
+    AFAIL(run_exporter);
+
+  exporter->parse_arguments (&argc, &argv);
+  exporter->do_export (0);
+
+  return 0;
+}
+/* --------------------------------------------------------------------------- */
 
 HID_Action action_action_list[] = {
   {"AddRats", 0, ActionAddRats,
@@ -6814,6 +6893,9 @@ HID_Action action_action_list[] = {
   {"ChangeDrillSize", 0, ActionChange2ndSize,
    changedrillsize_help, changedrillsize_syntax}
   ,
+  {"ChangeGroupVisibility", 0, ActionGroupVisibility,
+   change_group_visibility_help, change_group_visibility_syntax}
+  ,
   {"ChangeHole", 0, ActionChangeHole,
    changehold_help, changehold_syntax}
   ,
@@ -6969,6 +7051,9 @@ HID_Action action_action_list[] = {
   ,
   {"pscalib", 0, ActionPSCalib}
   ,
+  {"RunExporter", 0, RunExporter,
+   run_exporter_help, run_exporter_syntax}
+  ,
 };
 
 REGISTER_ACTIONS (action_action_list)
-- 
1.6.2.4

From 7253fcf43f13a290db529370b483708b22ecfc4f Mon Sep 17 00:00:00 2001
From: Ineiev <ineiev@xxxxxxxxxxxxxxxx>
Date: Mon, 22 Jun 2009 07:32:40 +0400
Subject: [PATCH 3/4] extend photo-flip options to non-photo mode

In non-photo mode, these options don't replace
component-oriented the layer stack with it's solder conterpart;
to do this --as-shown option combined with ChangeGroupVisibility
can be used
---
 ChangeLog         |    4 ++++
 src/hid/png/png.c |   47 +++++++++++++++++++++++++++++++----------------
 2 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8634bdc..9dd1892 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2009-06-21 17:17  ineiev
 
+	* src/hid/png/png.c: make --photo-flip-[xy] act in non-photo mode
+
+2009-06-21 17:17  ineiev
+
 	* src/action.c: add RunExporter and ChangeGroupVisibility actions
 
 2009-06-21 17:17  ineiev
diff --git a/src/hid/png/png.c b/src/hid/png/png.c
index ead57a3..beea2fb 100644
--- a/src/hid/png/png.c
+++ b/src/hid/png/png.c
@@ -505,17 +505,17 @@ png_do_export (HID_Attr_Val * options)
       memset (photo_copper, 0, sizeof(photo_copper));
       photo_silk = photo_mask = photo_drill = 0;
       photo_outline = 0;
-      if (options[HA_photo_flip_x].int_value
-	  || options[HA_ben_flip_x].int_value)
-	photo_flip = PHOTO_FLIP_X;
-      else if (options[HA_photo_flip_y].int_value
-	       || options[HA_ben_flip_y].int_value)
-	photo_flip = PHOTO_FLIP_Y;
-      else
-	photo_flip = 0;
     }
   else
     photo_mode = 0;
+  if (options[HA_photo_flip_x].int_value
+      || options[HA_ben_flip_x].int_value)
+    photo_flip = PHOTO_FLIP_X;
+  else if (options[HA_photo_flip_y].int_value
+      || options[HA_ben_flip_y].int_value)
+    photo_flip = PHOTO_FLIP_Y;
+  else
+    photo_flip = 0;
 
   filename = options[HA_pngfile].str_value;
   if (!filename)
@@ -780,17 +780,32 @@ png_do_export (HID_Attr_Val * options)
 		  gdImageColorResolve(im, 0, 0, 0):\
 		  gdImageColorResolve(im, p.r, p.g, p.b);
 	      }		  
-
-	      if (photo_flip == PHOTO_FLIP_X)
-		gdImageSetPixel (im, gdImageSX (im) - x - 1, y, cc);
-	      else if (photo_flip == PHOTO_FLIP_Y)
-		gdImageSetPixel (im, x, gdImageSY (im) - y - 1, cc);
-	      else
-		gdImageSetPixel (im, x, y, cc);
+	      gdImageSetPixel (im, x, y, cc);
 	    }
 	}
     }
-
+    if (photo_flip)
+      {
+	int c0, c1, x, y;
+	if (photo_flip == PHOTO_FLIP_X)
+	  for (x=0; x<gdImageSX (im)/2; x++)
+	    for (y=0; y<gdImageSY (im); y++)
+	      {
+	        c0 = gdImageGetPixel (im, x, y);
+	        c1 = gdImageGetPixel (im, gdImageSX (im) - x - 1, y);
+	        gdImageSetPixel (im, gdImageSX (im) - x - 1, y, c0);
+	        gdImageSetPixel (im, x, y, c1);
+	      }
+	if (photo_flip == PHOTO_FLIP_Y)
+	  for (y=0; y<gdImageSY (im)/2; y++)
+	    for (x=0; x<gdImageSX (im); x++)
+	      {
+	        c0 = gdImageGetPixel (im, x, y);
+	        c1 = gdImageGetPixel (im, x, gdImageSY (im) - y - 1);
+	        gdImageSetPixel (im, x, gdImageSY (im) - y - 1, c0);
+	        gdImageSetPixel (im, x, y, c1);
+	      }
+      }
   /* actually write out the image */
   fmt = filetypes[options[HA_filetype].int_value];
   
-- 
1.6.2.4

From 8b35472d667f585362af3bb6e1b66500afbc0a0e Mon Sep 17 00:00:00 2001
From: Ineiev <ineiev@xxxxxxxxxxxxxxxx>
Date: Sun, 21 Jun 2009 19:35:08 +0000
Subject: [PATCH 4/4] distinguish selected objects in photo mode

consider "#00ffff" color selected in photo mode;
remap it as red;

fix some hugest memory pours
---
 ChangeLog         |    5 +
 src/hid/png/png.c |  299 +++++++++++++++++++++++++++--------------------------
 2 files changed, 156 insertions(+), 148 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 9dd1892..8b4cb8e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2009-06-21 17:17  ineiev
 
+	* src/hid/png/png.c: consider "#00ffff" color as selected in
+	photo mode; output it in red; fix some hugest memory pours
+
+2009-06-21 17:17  ineiev
+
 	* src/hid/png/png.c: make --photo-flip-[xy] act in non-photo mode
 
 2009-06-21 17:17  ineiev
diff --git a/src/hid/png/png.c b/src/hid/png/png.c
index beea2fb..21fdc3c 100644
--- a/src/hid/png/png.c
+++ b/src/hid/png/png.c
@@ -16,7 +16,7 @@
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
 
@@ -52,9 +52,6 @@
 
 #define CRASH fprintf(stderr, "HID error: pcb called unimplemented PNG function %s.\n", __FUNCTION__); abort()
 
-static void *color_cache = NULL;
-static void *brush_cache = NULL;
-
 static double bloat = 0;
 static double scale = 1;
 static int x_shift = 0;
@@ -85,12 +82,11 @@ typedef struct hid_gc_struct
   gdImagePtr brush;
 } hid_gc_struct;
 
-static color_struct *black = NULL, *white = NULL;
+static color_struct black, white, other_color;
 static gdImagePtr im = NULL, master_im;
 static FILE *f = 0;
 static int linewidth = -1;
 static int lastgroup = -1;
-static gdImagePtr lastbrush = (void *) -1;
 static int lastcap = -1;
 static int lastcolor = -1;
 static int print_group[MAX_LAYER];
@@ -107,9 +103,9 @@ static int print_layer[MAX_LAYER];
 #define PHOTO_FLIP_X	1
 #define PHOTO_FLIP_Y	2
 
-static int photo_mode, photo_flip;
+static int photo_mode, photo_flip, selected_flag;
 static gdImagePtr photo_copper[MAX_LAYER+2];
-static gdImagePtr photo_silk, photo_mask, photo_drill, *photo_im;
+static gdImagePtr photo_silk, photo_mask, photo_drill, photo_selected, *photo_im;
 static gdImagePtr photo_outline;
 static int photo_groups[MAX_LAYER+2], photo_ngroups;
 
@@ -232,7 +228,13 @@ png_get_export_options (int *n)
   static char *last_made_filename = 0;
   const char *suffix = get_file_suffix();
 
-  if (PCB) derive_default_filename(PCB->Filename, &png_attribute_list[HA_pngfile], suffix, &last_made_filename);
+  if (PCB)
+    {
+      if (last_made_filename)
+	free (last_made_filename);
+      derive_default_filename(PCB->Filename, &png_attribute_list[HA_pngfile],
+			      suffix, &last_made_filename);
+    }
 
   if (n)
     *n = NUM_OPTIONS;
@@ -370,7 +372,6 @@ png_hid_export_to_file (FILE * the_file, HID_Attr_Val * options)
 	}
     }
   linewidth = -1;
-  lastbrush = (void *) -1;
   lastcap = -1;
   lastgroup = -1;
   lastcolor = -1;
@@ -476,18 +477,6 @@ png_do_export (HID_Attr_Val * options)
   int xmax, ymax, dpi;
   const char *fmt;
 
-  if (color_cache)
-    {
-      free (color_cache);
-      color_cache = NULL;
-    }
-
-  if (brush_cache)
-    {
-      free (brush_cache);
-      brush_cache = NULL;
-    }
-
   if (!options)
     {
       png_get_export_options (0);
@@ -503,7 +492,7 @@ png_do_export (HID_Attr_Val * options)
       options[HA_mono].int_value = 1;
       options[HA_as_shown].int_value = 0;
       memset (photo_copper, 0, sizeof(photo_copper));
-      photo_silk = photo_mask = photo_drill = 0;
+      photo_silk = photo_mask = photo_drill = photo_selected = 0;
       photo_outline = 0;
     }
   else
@@ -626,18 +615,15 @@ png_do_export (HID_Attr_Val * options)
    * Allocate white and black -- the first color allocated
    * becomes the background color
    */
-
-  white = (color_struct *) malloc (sizeof (color_struct));
-  white->r = white->g = white->b = 255;
+  white.r = white.g = white.b = 255;
   if (options[HA_use_alpha].int_value)
-    white->a = 127;
+    white.a = 127;
   else
-    white->a = 0;
-  white->c = gdImageColorAllocateAlpha (im, white->r, white->g, white->b, white->a);
+    white.a = 0;
+  white.c = gdImageColorAllocateAlpha (im, white.r, white.g, white.b, white.a);
 
-  black = (color_struct *) malloc (sizeof (color_struct));
-  black->r = black->g = black->b = black->a = 0;
-  black->c = gdImageColorAllocate (im, black->r, black->g, black->b);
+  black.r = black.g = black.b = black.a = 0;
+  black.c = gdImageColorAllocate (im, black.r, black.g, black.b);
 
   f = fopen (filename, "wb");
   if (!f)
@@ -657,16 +643,22 @@ png_do_export (HID_Attr_Val * options)
   if (photo_mode)
     {
       int x, y;
-      color_struct white, black, fr4;
+      color_struct white, black, fr4, selected;
 
       rgb (&white, 255, 255, 255);
       rgb (&black, 0, 0, 0);
       rgb (&fr4, 70, 70, 70);
+      rgb (&selected, 255, 0, 0);
 
       im = master_im;
 
+      photo_selected = gdImageCreate (gdImageSX (im), gdImageSY (im));
+      gdImageColorAllocate (photo_selected, 255, 255, 255);
+      gdImageColorAllocate (photo_selected, 0, 0, 0);
+
       ts_bs (photo_copper[photo_groups[0]]);
       ts_bs (photo_silk);
+      ts_bs (photo_selected);
       ts_bs_sm (photo_mask);
 
       if (photo_outline) {
@@ -769,6 +761,9 @@ png_do_export (HID_Attr_Val * options)
 	      else
 		p = cop;
 	      
+	      if (photo_selected && gdImageGetPixel (photo_selected, x, y))
+		p = selected;
+
 	      if (options[HA_use_alpha].int_value) {
 
 		cc = (transparent)?\
@@ -784,6 +779,37 @@ png_do_export (HID_Attr_Val * options)
 	    }
 	}
     }
+    for (i=0; i < sizeof(photo_copper)/sizeof(*photo_copper); i++)
+      if (photo_copper[i])
+	{
+	  gdImageDestroy (photo_copper[i]);
+          photo_copper[i] = 0;
+	}
+    if (photo_silk)
+      {
+	gdImageDestroy (photo_silk);
+	photo_silk = 0;
+      }
+    if (photo_mask)
+      {
+	gdImageDestroy (photo_mask);
+	photo_mask = 0;
+      }
+    if (photo_drill)
+      {
+	gdImageDestroy (photo_drill);
+	photo_drill = 0;
+      }
+    if (photo_selected)
+      {
+	gdImageDestroy (photo_selected);
+	photo_selected = 0;
+      }
+    if (photo_outline)
+      {
+	gdImageDestroy (photo_outline);
+	photo_outline = 0;
+      }
     if (photo_flip)
       {
 	int c0, c1, x, y;
@@ -814,8 +840,7 @@ png_do_export (HID_Attr_Val * options)
     gdImageGif (im, f);
 #else
     {
-      gdImageDestroy (im);
-      return;
+      ;
     }
 #endif
   else if (strcmp (fmt, FMT_jpg) == 0)
@@ -823,8 +848,7 @@ png_do_export (HID_Attr_Val * options)
     gdImageJpeg (im, f, -1);
 #else
     {
-      gdImageDestroy (im);
-      return;
+      ;
     }
 #endif
   else if (strcmp (fmt, FMT_png) == 0)
@@ -832,8 +856,7 @@ png_do_export (HID_Attr_Val * options)
     gdImagePng (im, f);
 #else
     {
-      gdImageDestroy (im);
-      return;
+      ;
     }
 #endif
   else
@@ -850,9 +873,12 @@ extern void hid_parse_command_line (int *argc, char ***argv);
 static void
 png_parse_arguments (int *argc, char ***argv)
 {
-  hid_register_attributes (png_attribute_list,
+  static int registered;
+  if (!registered)
+    hid_register_attributes (png_attribute_list,
 			   sizeof (png_attribute_list) /
 			   sizeof (png_attribute_list[0]));
+  registered = !0;
   hid_parse_command_line (argc, argv);
 }
 
@@ -928,21 +954,15 @@ png_set_layer (const char *name, int group, int empty)
 
       if (! *photo_im)
 	{
-	  static color_struct *black = NULL, *white = NULL;
+	  int black_c;
 	  *photo_im = gdImageCreate (gdImageSX (im), gdImageSY (im));
 
-	  white = (color_struct *) malloc (sizeof (color_struct));
-	  white->r = white->g = white->b = 255;
-	  white->a = 0;
-	  white->c = gdImageColorAllocate (*photo_im, white->r, white->g, white->b);
-
-	  black = (color_struct *) malloc (sizeof (color_struct));
-	  black->r = black->g = black->b = black->a = 0;
-	  black->c = gdImageColorAllocate (*photo_im, black->r, black->g, black->b);
+	  gdImageColorAllocate (*photo_im, 255, 255, 255);
+	  black_c = gdImageColorAllocate (*photo_im, 0, 0, 0);
 
 	  if (idx == SL (PDRILL, 0)
 	      || idx == SL (UDRILL, 0))
-	    gdImageFilledRectangle (*photo_im, 0, 0, gdImageSX (im), gdImageSY (im), black->c);
+	    gdImageFilledRectangle (*photo_im, 0, 0, gdImageSX (im), gdImageSY (im), black_c);
 	}
       im = *photo_im;
       return 1;
@@ -985,10 +1005,11 @@ static hidGC
 png_make_gc (void)
 {
   hidGC rv = (hidGC) malloc (sizeof (hid_gc_struct));
+  memset (rv, 0, sizeof(rv));
   rv->me_pointer = &png_hid;
   rv->cap = Trace_Cap;
   rv->width = 1;
-  rv->color = (color_struct *) malloc (sizeof (color_struct));
+  rv->color = &other_color;
   rv->color->r = rv->color->g = rv->color->b = rv->color->a = 0;
   rv->color->c = 0;
   return rv;
@@ -997,6 +1018,8 @@ png_make_gc (void)
 static void
 png_destroy_gc (hidGC gc)
 {
+  if (gc->brush)
+    gdImageDestroy (gc->brush);
   free (gc);
 }
 
@@ -1009,7 +1032,7 @@ png_use_mask (int use_it)
 static void
 png_set_color (hidGC gc, const char *name)
 {
-  hidval cval;
+  selected_flag = photo_mode && !strcmp(name,"#00ffff");
 
   if (im == NULL)
     return;
@@ -1020,7 +1043,7 @@ png_set_color (hidGC gc, const char *name)
   if (strcmp (name, "erase") == 0 || strcmp (name, "drill") == 0)
     {
       /* FIXME -- should be background, not white */
-      gc->color = white;
+      gc->color = &white;
       gc->erase = 1;
       return;
     }
@@ -1028,30 +1051,27 @@ png_set_color (hidGC gc, const char *name)
 
   if (in_mono || (strcmp (name, "#000000") == 0))
     {
-      gc->color = black;
+      gc->color = &black;
       return;
     }
 
-  if (hid_cache_color (0, name, &cval, &color_cache))
+   if (name[0] == '#')
     {
-      gc->color = cval.ptr;
-    }
-  else if (name[0] == '#')
-    {
-      gc->color = (color_struct *) malloc (sizeof (color_struct));
+      gc->color = &other_color;
       sscanf (name + 1, "%2x%2x%2x", &(gc->color->r), &(gc->color->g),
 	      &(gc->color->b));
       gc->color->c =
-	gdImageColorAllocate (im, gc->color->r, gc->color->g, gc->color->b);
-      cval.ptr = gc->color;
-      hid_cache_color (1, name, &cval, &color_cache);
+	gdImageColorExact (im, gc->color->r, gc->color->g, gc->color->b);
+      if (gc->color->c == -1)
+	gc->color->c =
+	  gdImageColorAllocate (im, gc->color->r,
+				gc->color->g, gc->color->b);
     }
   else
     {
       printf ("WE SHOULD NOT BE HERE!!!\n");
-      gc->color = black;
+      gc->color = &black;
     }
-
 }
 
 static void
@@ -1087,7 +1107,10 @@ png_set_line_cap_angle (hidGC gc, int x1, int y1, int x2, int y2)
 static void
 use_gc (hidGC gc)
 {
-  int need_brush = 0;
+  gdImagePtr image = selected_flag? photo_selected: im;
+  char type;
+  int r;
+  int bg, fg;
 
   if (gc->me_pointer != &png_hid)
     {
@@ -1099,80 +1122,55 @@ use_gc (hidGC gc)
     {
       /* Make sure the scaling doesn't erase lines completely */
       if (SCALE (gc->width) == 0 && gc->width > 0)
-	gdImageSetThickness (im, 1);
+	gdImageSetThickness (image, 1);
       else
-	gdImageSetThickness (im, SCALE (gc->width + 2*bloat));
+	gdImageSetThickness (image, SCALE (gc->width + 2*bloat));
       linewidth = gc->width;
-      need_brush = 1;
     }
 
-  if (lastbrush != gc->brush || need_brush)
+  switch (gc->cap)
     {
-      hidval bval;
-      char name[256];
-      char type;
-      int r;
-
-      switch (gc->cap)
-        {
-        case Round_Cap:
-        case Trace_Cap:
-          type = 'C';
-          break;
-        default:
-        case Square_Cap:
-          type = 'S';
-          break;
-        }
-      if (gc->width)
-	r = SCALE (gc->width + 2*bloat);
-      else
-	r = 1;
-      sprintf (name, "#%.2x%.2x%.2x_%c_%d", gc->color->r, gc->color->g,
-	       gc->color->b, type, r);
-
-      if (hid_cache_color (0, name, &bval, &brush_cache))
-	{
-	  gc->brush = bval.ptr;
-	}
-      else
-	{
-	  int bg, fg;
-	  gc->brush = gdImageCreate (r, r);
-	  bg = gdImageColorAllocate (gc->brush, 255, 255, 255);
-	  fg =
-	    gdImageColorAllocateAlpha (gc->brush, gc->color->r, gc->color->g,
-				       gc->color->b, 0); 
-	  gdImageColorTransparent (gc->brush, bg);
-
-	  /*
-	   * if we shrunk to a radius/box width of zero, then just use
-	   * a single pixel to draw with.
-	   */
-	  if (r <= 1)
-	    gdImageFilledRectangle (gc->brush, 0, 0, 0, 0, fg);
-	  else
-	    {
-	      if (type == 'C')
-		{
-		  gdImageFilledEllipse (gc->brush, r/2, r/2, r, r, fg);
-		  /* Make sure the ellipse is the right exact size.  */
-		  gdImageSetPixel (gc->brush, 0, r/2, fg);
-		  gdImageSetPixel (gc->brush, r-1, r/2, fg);
-		  gdImageSetPixel (gc->brush, r/2, 0, fg);
-		  gdImageSetPixel (gc->brush, r/2, r-1, fg);
-		}
-	      else
-		gdImageFilledRectangle (gc->brush, 0, 0, r-1, r-1, fg);
-	    }
-	  bval.ptr = gc->brush;
-	  hid_cache_color (1, name, &bval, &brush_cache);
-	}
+    case Round_Cap:
+    case Trace_Cap:
+      type = 'C';
+      break;
+    default:
+    case Square_Cap:
+      type = 'S';
+      break;
+    }
+  if (gc->width)
+    r = SCALE (gc->width + 2*bloat);
+  else
+    r = 1;
 
-      gdImageSetBrush (im, gc->brush);
-      lastbrush = gc->brush;
+  if (gc->brush)
+    gdImageDestroy (gc->brush);
+  gc->brush = gdImageCreate (r, r);
+  bg = gdImageColorAllocate (gc->brush, 255, 255, 255);
+  fg =
+    gdImageColorAllocateAlpha (gc->brush, gc->color->r,
+			       gc->color->g, gc->color->b, 0);
+  gdImageColorTransparent (gc->brush, bg);
 
+  /*
+   * if we shrunk to a radius/box width of zero, then just use
+   * a single pixel to draw with.
+   */
+  if (r <= 1)
+    gdImageFilledRectangle (gc->brush, 0, 0, 0, 0, fg);
+  else if (type == 'C')
+    {
+      gdImageFilledEllipse (gc->brush, r/2, r/2, r, r, fg);
+      /* Make sure the ellipse is the right exact size.  */
+      gdImageSetPixel (gc->brush, 0, r/2, fg);
+      gdImageSetPixel (gc->brush, r-1, r/2, fg);
+      gdImageSetPixel (gc->brush, r/2, 0, fg);
+      gdImageSetPixel (gc->brush, r/2, r-1, fg);
     }
+  else
+    gdImageFilledRectangle (gc->brush, 0, 0, r-1, r-1, fg);
+  gdImageSetBrush (image, gc->brush);
 
 #define CBLEND(gc) (((gc->r)<<24)|((gc->g)<<16)|((gc->b)<<8)|(gc->faded))
   if (lastcolor != CBLEND (gc))
@@ -1211,7 +1209,7 @@ static void
 png_draw_rect (hidGC gc, int x1, int y1, int x2, int y2)
 {
   use_gc (gc);
-  gdImageRectangle (im,
+  gdImageRectangle (selected_flag? photo_selected: im,
 		    SCALE_X (x1), SCALE_Y (y1),
 		    SCALE_X (x2), SCALE_Y (y2), gc->color->c);
 }
@@ -1219,8 +1217,10 @@ png_draw_rect (hidGC gc, int x1, int y1, int x2, int y2)
 static void
 png_fill_rect (hidGC gc, int x1, int y1, int x2, int y2)
 {
+  gdImagePtr image = selected_flag? photo_selected: im;
+
   use_gc (gc);
-  gdImageSetThickness (im, 0);
+  gdImageSetThickness (image, 0);
   linewidth = 0;
 
   if (x1 > x2)
@@ -1236,13 +1236,15 @@ png_fill_rect (hidGC gc, int x1, int y1, int x2, int y2)
       y2 = t;
     }
 
-  gdImageFilledRectangle (im, SCALE_X (x1-bloat), SCALE_Y (y1-bloat),
+  gdImageFilledRectangle (image, SCALE_X (x1-bloat), SCALE_Y (y1-bloat),
 			  SCALE_X (x2+bloat)-1, SCALE_Y (y2+bloat)-1, gc->color->c);
 }
 
 static void
 png_draw_line (hidGC gc, int x1, int y1, int x2, int y2)
 {
+  gdImagePtr image = selected_flag? photo_selected: im;
+
   if (x1 == x2 && y1 == y2)
     {
       int w = gc->width / 2;
@@ -1251,13 +1253,11 @@ png_draw_line (hidGC gc, int x1, int y1, int x2, int y2)
     }
   use_gc (gc);
 
-  gdImageSetThickness (im, 0);
+  gdImageSetThickness (image, 0);
   linewidth = 0;
   if(gc->cap != Square_Cap || x1 == x2 || y1 == y2 )
-    {
-      gdImageLine (im, SCALE_X (x1), SCALE_Y (y1),
+    gdImageLine (image, SCALE_X (x1), SCALE_Y (y1),
 		   SCALE_X (x2), SCALE_Y (y2), gdBrushed);
-    }
   else
     {
       /*
@@ -1265,8 +1265,8 @@ png_draw_line (hidGC gc, int x1, int y1, int x2, int y2)
        * not purely horizontal or vertical, then we need to draw
        * it as a filled polygon.
        */
-      int fg = gdImageColorResolve (im, gc->color->r, gc->color->g,
-				    gc->color->b),
+      int fg = gdImageColorResolve (image, gc->color->r,
+				    gc->color->g, gc->color->b),
 	w = gc->width, dx = x2 - x1, dy = y2 - y1, dwx, dwy;
       gdPoint p[4];
       double l = sqrt (dx * dx + dy * dy) * 2 * scale;
@@ -1277,7 +1277,7 @@ png_draw_line (hidGC gc, int x1, int y1, int x2, int y2)
       p[1].x = SCALE_X (x1) - dwx - dwy; p[1].y = SCALE_Y(y1) - dwy + dwx;
       p[2].x = SCALE_X (x2) - dwx + dwy; p[2].y = SCALE_Y(y2) - dwy - dwx;
       p[3].x = SCALE_X (x2) + dwx + dwy; p[3].y = SCALE_Y(y2) + dwy - dwx;
-      gdImageFilledPolygon (im, p, 4, fg);
+      gdImageFilledPolygon (image, p, 4, fg);
     }
 }
 
@@ -1327,20 +1327,22 @@ png_draw_arc (hidGC gc, int cx, int cy, int width, int height,
 	  SCALE (width), SCALE (height), sa, ea, gc->color->c);
 #endif
   use_gc (gc);
-  gdImageSetThickness (im, 0);
+  gdImageSetThickness (selected_flag? photo_selected: im, 0);
   linewidth = 0;
-  gdImageArc (im, SCALE_X (cx), SCALE_Y (cy),
+  gdImageArc (selected_flag? photo_selected: im, SCALE_X (cx), SCALE_Y (cy),
 	      SCALE (2 * width), SCALE (2 * height), sa, ea, gdBrushed);
 }
 
 static void
 png_fill_circle (hidGC gc, int cx, int cy, int radius)
 {
+  gdImagePtr image = selected_flag? photo_selected: im;
+
   use_gc (gc);
 
-  gdImageSetThickness (im, 0);
+  gdImageSetThickness (image, 0);
   linewidth = 0;
-  gdImageFilledEllipse (im, SCALE_X (cx), SCALE_Y (cy),
+  gdImageFilledEllipse (image, SCALE_X (cx), SCALE_Y (cy),
 			SCALE (2 * radius + 2*bloat), SCALE (2 * radius + 2*bloat), gc->color->c);
 
 }
@@ -1350,6 +1352,7 @@ png_fill_polygon (hidGC gc, int n_coords, int *x, int *y)
 {
   int i;
   gdPoint *points;
+  gdImagePtr image = selected_flag? photo_selected: im;
 
   points = (gdPoint *) malloc (n_coords * sizeof (gdPoint));
   if (points == NULL)
@@ -1364,9 +1367,9 @@ png_fill_polygon (hidGC gc, int n_coords, int *x, int *y)
       points[i].x = SCALE_X (x[i]);
       points[i].y = SCALE_Y (y[i]);
     }
-  gdImageSetThickness (im, 0);
+  gdImageSetThickness (image, 0);
   linewidth = 0;
-  gdImageFilledPolygon (im, points, n_coords, gc->color->c);
+  gdImageFilledPolygon (image, points, n_coords, gc->color->c);
   free (points);
 }
 
-- 
1.6.2.4


_______________________________________________
geda-user mailing list
geda-user@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user