Commits

Martin Vejnár committed f70da7e

Initial commit, version 1.1 by Nils Springob.

Comments (0)

Files changed (1)

+#usage "<b>Eagle schematic exporting tool  version 1.0 </b>\n"
+       "<p>"
+       "This ULP can convert an Eagle CAD schematics into SVG files."
+       "<p>"
+       "Load any schematic and execute the ULP in the eagle."
+       "<p>"
+       "<author>Author: nils.springob (at) nicai-systems.de</author><br>"
+       "based on eagle2ps by juergen.messerer (at) freesurf.ch<br>"
+       "<br>"
+       "Known issues in board export:<ul>"
+       "<li>drill-symbols are not supported"
+       "<li>elongated pads are not supported"
+       "<li>non vector-text is not rotated correctly"
+       "</ul>"
+       
+real VERSION   = 1.1;
+
+/*
+ * CHANGELOG================================================
+ *
+ * 1.1 (??.04.2008): SVG export for board files      
+ * 1.0 (16.04.2008): Some bugfixes      
+ * 0.2 (11.04.2008): Using CSS for layer-styles      
+ * 0.1 (08.03.2008): Initial version    
+ *
+ */  
+
+/* ==========================================================================
+ * License: This file is released under the license of the GNU Public license
+ *          Version 2.
+ * ==========================================================================*/   
+ 
+
+int g_monochrome = 0;
+int g_only_visible = 1;
+int g_used_layers[];
+
+
+//------------------------------------------------------
+// generate html color code  
+//------------------------------------------------------
+string htmlcolor(int col) {
+  string result;
+  sprintf(result, "#%06x", col);
+  return result;
+}
+
+
+//------------------------------------------------------
+// replace xml reserved chars and build 2-byte utf-8 characters  
+//------------------------------------------------------
+string encodeText(string strText) {
+  string newText = "";
+  int i=0;
+  
+  while (strText[i]) {
+    char c = strText[i++];
+    switch(c) {
+      case '<': newText += "&lt;"; break; 
+      case '>': newText += "&gt;"; break;
+      case '&': newText += "&amp;"; break;
+      default:
+        if (c>=0xc0) {
+          newText += char(0xc3);
+          newText += char(c-0x40);
+        } else if (c>=0x80) {
+          newText += char(0xc2);
+          newText += char(c);
+        } else {
+          newText += c;
+        }
+    }
+  }
+  return newText;
+}
+
+//------------------------------------------------------
+// SVG output functions
+//------------------------------------------------------
+
+string svgLineStyle(int width, int cap) {
+  string lineCap="round";
+
+  switch (cap) {
+    case CAP_FLAT: lineCap = "butt"; break;
+    case CAP_ROUND: lineCap = "round"; break;
+    default: lineCap = "round"; break;
+  }
+
+  string style;
+  sprintf(style, "stroke-width:%f; stroke-linecap:%s",
+    u2mm(width), lineCap);
+  return style;    
+}
+
+string svgTransform(int x, int y, real angle) {
+  string trans, rot, res;
+  sprintf(trans, "translate(%f,%f)", u2mm(x), u2mm(-y));
+  sprintf(rot, "rotate(%f)", -angle);
+  return "transform='"+trans+" "+rot+"'";
+}
+
+void svgWriteLine(int x1, int y1, int x2, int y2, int layer, string style) {
+  printf("<line class='l%d' x1='%f' y1='%f' x2='%f' y2='%f' style='%s'/>\n",
+    layer,
+    u2mm(x1), u2mm(-y1), 
+    u2mm(x2), u2mm(-y2),
+    style);
+}
+
+void svgWriteArc(int x1, int y1, int x2, int y2, int radius, char longpath, int layer, string style) {
+  printf("<path class='l%d' d='M %f,%f A %f %f 0 %c 0 %f,%f' style='%s'/>\n",
+    layer,
+    u2mm(x1), u2mm(-y1),
+    u2mm(radius), u2mm(radius),
+    longpath,
+    u2mm(x2), u2mm(-y2),
+    style);
+}
+
+void svgWriteRect(int x1, int y1, int x2, int y2, real angle, int layer) {
+  if (g_used_layers[layer]==0) {
+    return;
+  }
+  string rotation="";
+
+  if (angle!=0.0) {
+    sprintf(rotation, " transform='rotate(%f,%f,%f)'",
+      -angle, 
+      u2mm(x1+x2)/2.0, u2mm(-y1-y2)/2.0);
+  }   
+  printf("<rect class='l%d' x='%f' y='%f' width='%f' height='%f'%s/>\n",
+    layer,
+    u2mm(x1), u2mm(-y2), 
+    u2mm(x2-x1), u2mm(y2-y1),
+    rotation);
+}
+
+void svgWriteRectCenter(int x, int y, int dx, int dy, real angle, int layer) {
+  if (g_used_layers[layer]==0) {
+    return;
+  }
+  string rotation = svgTransform(x, y, angle);
+
+  printf("<rect class='l%d' x='%f' y='%f' width='%f' height='%f' %s/>\n",
+    layer,
+    u2mm(-dx/2), u2mm(-dy/2), 
+    u2mm(dx), u2mm(dy),
+    rotation);
+}
+
+void svgWriteOctCenter(int x, int y, int dx, int dy, real angle, int layer) {
+  if (g_used_layers[layer]==0) {
+    return;
+  }
+  string rotation = svgTransform(x, y, angle);
+
+  real x1 = u2mm(dx)/2; 
+  real y1 = u2mm(dy)/2; 
+  real x2 = u2mm(dx)/(2*(1+1.414213562));
+  real y2 = u2mm(dy)/(2*(1+1.414213562)); 
+
+  printf("<polygon class='l%d' points='%f %f, %f %f, %f %f, %f %f, %f %f, %f %f, %f %f, %f %f' %s/>\n",
+    layer,
+    -x1, -y2, 
+    -x2, -y1, 
+    x2, -y1, 
+    x1, -y2, 
+    x1, y2, 
+    x2, y1, 
+    -x2, y1, 
+    -x1, y2, 
+    rotation);
+}
+
+void svgWriteRoundRectCenter(int x, int y, int w, int h, int roundness, real angle, int layer) {
+  if (g_used_layers[layer]==0) {
+    return;
+  }
+  string rotation = svgTransform(x, y, angle);
+
+  if (w<h){
+    roundness = w*roundness/200;
+  } else {
+    roundness = h*roundness/200;
+  }
+
+  printf("<rect class='l%d' x='%f' y='%f' width='%f' height='%f' rx='%f' %s/>\n",
+    layer,
+    u2mm(-w/2), u2mm(-h/2), 
+    u2mm(w), u2mm(h),
+    u2mm(roundness),
+    rotation);
+}
+
+
+void svgWriteCircle(int x, int y, int radius, int lwidth, int layer) {
+  if (g_used_layers[layer]==0) {
+    return;
+  }
+  printf("<circle class='l%d' cx='%f' cy='%f' r='%f' style='stroke-width:%f'/>\n", 
+    layer,
+    u2mm(x), u2mm(-y),
+    u2mm(radius), 
+    u2mm(lwidth));
+}
+
+void svgWriteDot(int x, int y, int diameter, int layer) {
+  if (g_used_layers[layer]==0) {
+    return;
+  }
+  printf("<circle class='j%d' cx='%f' cy='%f' r='%f'/>\n", 
+    layer,
+    u2mm(x), u2mm(-y),
+    u2mm(diameter)/2.0);
+}
+
+
+void svgWritePathStart(int layer, string style) {
+  printf( "<path class='l%d' style='%s' d='", layer, style);
+}
+
+void svgWritePathSegment(int x1, int y1, int x2, int y2) {
+  printf( " M %f,%f L %f,%f", u2mm(x1), u2mm(-y1), u2mm(x2), u2mm(-y2));    
+}
+
+void svgWritePathEnd() {
+  printf( "'/>\n");
+}
+
+
+
+void svgWriteText(int x, int y, real angle, char align, string text, int size, int layer) {
+  if (g_used_layers[layer]==0) {
+    return;
+  }
+  string style;
+  sprintf(style, "font-size:%fpt;", u2mm(size)*1.1);
+
+  if (align=='e') {
+    style += " text-anchor:end;";
+  }
+
+  if (angle==0.0) {
+    printf( "<text class='l%d' x='%f' y='%f' style='%s'>%s</text>\n",
+      layer,
+      u2mm(x), u2mm(-y), 
+      style, 
+      text);
+  
+  } else {
+    printf( "<text class='l%d' x='0' y='0' style='%s' transform='translate(%f, %f) rotate(%f)'>%s</text>\n",
+      layer,
+      style,
+      u2mm(x), u2mm(-y), 
+      angle,
+      text);  
+  }
+}
+
+
+
+//------------------------------------------------------
+// write UL piece
+//------------------------------------------------------
+void write_piece(UL_WIRE W) {
+  if (g_used_layers[W.layer]==0) {
+    return;
+  }
+
+  string style = svgLineStyle(W.width, W.cap);
+      
+  if (W.arc) {
+    char longpath;
+    if( abs(W.arc.angle2-W.arc.angle1) < 180.0 ) {
+      longpath='0';
+    } else {
+      longpath='1';
+    }
+    svgWriteArc(W.arc.x1, W.arc.y1, W.arc.x2, W.arc.y2, W.arc.radius, longpath, W.layer, style);
+  } else {
+    svgWriteLine(W.x1, W.y1, W.x2, W.y2, W.layer, style);
+  }
+}
+
+
+//------------------------------------------------------
+// write UL wire
+//------------------------------------------------------
+void write_wire(UL_WIRE W) {
+  if (g_used_layers[W.layer]==0) {
+    return;
+  }
+   
+  if ( W.style == WIRE_STYLE_LONGDASH || W.style == WIRE_STYLE_SHORTDASH || W.style == WIRE_STYLE_DASHDOT ) {
+    W.pieces(P) {
+      write_piece(P);           
+    }      
+  } else if (W.arc) {
+    string style = svgLineStyle(W.arc.width, W.cap);
+    char longpath;
+    if( abs(W.arc.angle2-W.arc.angle1) < 180.0 ) {
+      longpath='0';
+    } else {
+      longpath='1';
+    }
+    svgWriteArc(W.arc.x1, W.arc.y1, W.arc.x2, W.arc.y2, W.arc.radius, longpath, W.layer, style);   
+  } else {
+    string style = svgLineStyle(W.width, W.cap);
+    svgWriteLine(W.x1, W.y1, W.x2, W.y2, W.layer, style);
+  }
+}
+
+
+//------------------------------------------------------
+// write UL rectangle
+//------------------------------------------------------
+void write_rectangle(UL_RECTANGLE R) {
+  if (g_used_layers[R.layer]==0) {
+    return;
+  }
+  svgWriteRect(R.x1, R.y1, R.x2, R.y2, R.angle, R.layer);
+}
+
+
+//------------------------------------------------------
+// write UL vector text
+//------------------------------------------------------
+void write_vector_text(UL_TEXT T) {
+  if (g_used_layers[T.layer]==0) {
+    return;
+  }
+  int cnt=0;
+  T.wires(W) {
+    string lineCap;
+    if (cnt==0) {
+      string style = svgLineStyle(W.width, W.cap);
+      svgWritePathStart(W.layer, style);
+    }
+    svgWritePathSegment(W.x1, W.y1, W.x2, W.y2);
+    cnt++;
+  }
+  if (cnt>0) {
+    svgWritePathEnd();
+  }
+}
+
+//------------------------------------------------------
+// write UL proportional text
+//------------------------------------------------------
+void write_prop_text(UL_TEXT T) {
+  if (g_used_layers[T.layer]==0) {
+    return;
+  }
+
+  string newText = encodeText(T.value);
+   
+  int posX = T.x;
+  int posY = T.y;   
+  int textAngle = T.angle;
+  int textSize = T.size;
+  
+  char hmode, vmode, rmode;
+   
+  if( T.mirror > 0 ) {
+    switch( textAngle ) {
+      case 0:   vmode='e'; hmode='b'; rmode='0'; break;
+      case 90:  vmode='b'; hmode='t'; rmode='9'; break;
+      case 180: vmode='b'; hmode='t'; rmode='0'; break;
+      case 270: vmode='e'; hmode='b'; rmode='9'; break;
+    } 
+  } else {
+    switch( textAngle ) {
+      case 0:   vmode='b'; hmode='b'; rmode='0'; break;
+      case 90:  vmode='b'; hmode='b'; rmode='9'; break;
+      case 180: vmode='e'; hmode='t'; rmode='0'; break;
+      case 270: vmode='e'; hmode='t'; rmode='9'; break;
+    } 
+  }
+
+  if (rmode=='0') {
+    if (hmode=='t') {
+      posY -= textSize;
+    }
+    svgWriteText(posX, posY, 0.0, vmode, newText, textSize, T.layer);
+  } else {
+    if (hmode=='t') {
+      posX += textSize;
+    }
+    svgWriteText(posX, posY, -90.0, vmode, newText, textSize, T.layer);
+  }
+}
+
+
+//------------------------------------------------------
+// write UL general text
+//------------------------------------------------------
+void write_text(UL_TEXT T) {
+  if (g_used_layers[T.layer]==0) {
+    return;
+  }
+  if (T.font==FONT_VECTOR) {
+    write_vector_text(T);
+  } else {
+    write_prop_text(T);
+  }
+}
+
+
+
+//------------------------------------------------------
+// write UL circle
+//------------------------------------------------------
+void write_circle(UL_CIRCLE C) {
+  if (g_used_layers[C.layer]==0) {
+    return;
+  }
+  svgWriteCircle(C.x, C.y, C.radius, C.width, C.layer);
+}
+
+
+//------------------------------------------------------
+// write drillsymbol
+//------------------------------------------------------
+void write_drill(int x, int y, int drillsymbol, int layer) {
+  if (g_used_layers[layer]==0) {
+    return;
+  }
+  svgWriteCircle(x, y, 8000, 40, layer);
+}
+
+//------------------------------------------------------
+// write restring
+//------------------------------------------------------
+void write_restring(int x, int y, int diameter, int shape, int long, real angle, int layer) {
+  if (g_used_layers[layer]==0) {
+    return;
+  }
+  
+  switch(shape) {
+    case PAD_SHAPE_SQUARE:
+      svgWriteRectCenter(x, y, diameter, diameter, angle, layer);
+      break;
+    case PAD_SHAPE_OCTAGON: 
+      svgWriteOctCenter(x, y, diameter, diameter, angle, layer);
+      break;
+    case PAD_SHAPE_LONG:
+      svgWriteRoundRectCenter(x, y, (diameter*long)/100, diameter, 100, angle, layer);
+      break;
+    case PAD_SHAPE_OFFSET:
+    case PAD_SHAPE_ANNULUS:
+    case PAD_SHAPE_THERMAL:
+    case PAD_SHAPE_ROUND:
+    default:
+      svgWriteDot(x, y, diameter, layer);
+  }
+}
+
+
+//------------------------------------------------------
+// write UL pad
+//------------------------------------------------------
+void write_pad(UL_PAD P) {
+  int layer;
+  if (P.flags&PAD_FLAG_STOP) {
+    write_restring(P.x, P.y, P.diameter[LAYER_TSTOP], P.shape[LAYER_TSTOP], 100+P.elongation, P.angle, LAYER_TSTOP);
+    write_restring(P.x, P.y, P.diameter[LAYER_BSTOP], P.shape[LAYER_BSTOP], 100+P.elongation, P.angle, LAYER_BSTOP);
+  }
+  for (layer=LAYER_TOP; layer<=LAYER_BOTTOM; ++layer) {
+    if (g_used_layers[layer]) {
+      write_restring(P.x, P.y, P.diameter[layer], P.shape[layer], 100+P.elongation, P.angle, layer);
+    }
+  }
+  write_drill(P.x, P.y, P.drillsymbol, LAYER_DRILLS);
+}
+
+
+//------------------------------------------------------
+// write UL smd
+//------------------------------------------------------
+void write_smd(UL_SMD S) {
+  if (S.layer==LAYER_TOP) {
+    if (S.flags & SMD_FLAG_STOP) {
+      svgWriteRoundRectCenter(S.x, S.y, S.dx[LAYER_TSTOP], S.dy[LAYER_TSTOP], S.roundness, S.angle, LAYER_TSTOP);
+    }
+    if (S.flags & SMD_FLAG_CREAM) {
+      svgWriteRoundRectCenter(S.x, S.y, S.dx[LAYER_TCREAM], S.dy[LAYER_TCREAM], S.roundness, S.angle, LAYER_TCREAM);
+    }  
+    svgWriteRoundRectCenter(S.x, S.y, S.dx[LAYER_TOP], S.dy[LAYER_TOP], S.roundness, S.angle, LAYER_TOP);
+  } else if (S.layer==LAYER_BOTTOM) {
+    if (S.flags & SMD_FLAG_STOP) {
+      svgWriteRoundRectCenter(S.x, S.y, S.dx[LAYER_BSTOP], S.dy[LAYER_BSTOP], S.roundness, S.angle, LAYER_BSTOP);
+    }
+    if (S.flags & SMD_FLAG_CREAM) {
+      svgWriteRoundRectCenter(S.x, S.y, S.dx[LAYER_BCREAM], S.dy[LAYER_BCREAM], S.roundness, S.angle, LAYER_BCREAM);
+    }    
+    svgWriteRoundRectCenter(S.x, S.y, S.dx[LAYER_BOTTOM], S.dy[LAYER_BOTTOM], S.roundness, S.angle, LAYER_BOTTOM);
+  }
+}
+
+
+//------------------------------------------------------
+// write UL via
+//------------------------------------------------------
+void write_via(UL_VIA V) {
+  int layer;
+  if (V.flags&VIA_FLAG_STOP) {
+    write_restring(V.x, V.y, V.diameter[LAYER_TSTOP], V.shape[LAYER_TSTOP], 100, 0.0, LAYER_TSTOP);
+    write_restring(V.x, V.y, V.diameter[LAYER_BSTOP], V.shape[LAYER_BSTOP], 100, 0.0, LAYER_BSTOP);
+  }
+  for (layer=V.start; layer<=V.end; ++layer) {
+    if (g_used_layers[layer]) {
+      write_restring(V.x, V.y, V.diameter[layer], V.shape[layer], 100, 0.0, layer);
+    }
+  }
+  write_drill(V.x, V.y, V.drillsymbol, LAYER_DRILLS);
+}
+
+
+//------------------------------------------------------
+// write UL hole
+//------------------------------------------------------
+void write_hole(UL_HOLE H) { 
+  svgWriteCircle(H.x, H.y, H.drill/2, 1, LAYER_DIMENSION);
+  write_drill(H.x, H.y, H.drillsymbol, LAYER_HOLES);
+}
+
+
+//------------------------------------------------------
+// write UL segment
+//------------------------------------------------------
+void write_segment(UL_SEGMENT SEG) {
+  int layer = 0;      
+  SEG.wires(W) {
+    layer = W.layer;      
+    write_wire(W);
+  }
+  
+  SEG.junctions(J) {  
+    svgWriteDot(J.x, J.y, J.diameter, layer);
+  }
+
+  SEG.texts(T) {
+    write_text(T);
+  }
+}
+
+
+//------------------------------------------------------
+// write UL polygon
+//------------------------------------------------------
+void write_polygon(UL_POLYGON P) {
+  if (g_used_layers[P.layer]==0) {
+    return;
+  }
+  int count = 0;
+  printf( "<polygon class='l%d' points='", P.layer);
+
+  P.wires(W) {
+    if (count == 0) {
+      printf( "%f %f", u2mm(W.x1), u2mm(-W.y1)); 
+    } else {
+      printf( ", %f %f", u2mm(W.x1), u2mm(-W.y1));
+    }
+    ++count;
+  }
+
+  printf( "'/>\n" );
+
+}
+
+
+//------------------------------------------------------
+// write filled UL polygon
+//------------------------------------------------------
+void write_filled_polygon(UL_POLYGON P) {
+  if (g_used_layers[P.layer]==0) {
+    return;
+  }
+  string style;
+  int first=1;
+  
+  P.contours(W) {
+    if (first) {
+      string style = svgLineStyle(W.width, W.cap);
+      svgWritePathStart(P.layer, style);
+      first=0;
+    }
+    svgWritePathSegment(W.x1, W.y1, W.x2, W.y2);
+  }
+  P.fillings(W) {
+    svgWritePathSegment(W.x1, W.y1, W.x2, W.y2);
+  }
+  svgWritePathEnd();
+}
+
+
+//------------------------------------------------------
+// write UL bus
+//------------------------------------------------------
+void write_bus(UL_BUS B) {
+  printf("<g><title>BUS %s</title>\n", encodeText(B.name));
+  B.segments(SEG) {
+    write_segment(SEG);
+  }
+  printf("</g>\n");
+}
+
+
+//------------------------------------------------------
+// write UL net
+//------------------------------------------------------
+void write_net(UL_NET N) {
+  printf("<g><title>NET %s</title>\n", encodeText(N.name));
+  N.segments(SEG) {
+    write_segment(SEG);
+  }
+  printf("</g>\n");
+}
+
+
+//------------------------------------------------------
+//write UL signal
+//------------------------------------------------------
+void write_signal(UL_SIGNAL S) {
+  S.polygons(P) {write_filled_polygon(P);}    
+  S.wires(W)    {write_wire(W);}
+  S.vias(V)     {write_via(V);}    
+}
+
+
+//------------------------------------------------------
+//write UL pin
+//------------------------------------------------------
+void write_pin(UL_PIN P) {
+  P.wires(W)   {write_wire(W);}
+  P.circles(C) {write_circle(C);}
+  P.texts(T)   {write_text(T);}
+}
+
+
+//------------------------------------------------------
+//write UL symbol
+//------------------------------------------------------
+void write_symbol(UL_SYMBOL S) {
+  S.polygons(P)   {write_polygon(P);}
+  S.circles(C)    {write_circle(C);}
+  S.rectangles(R) {write_rectangle(R);}
+  S.pins(P)       {write_pin(P);}
+  S.wires(W)      {write_wire(W);}
+  S.texts(T)      {write_text(T);}
+}
+
+
+//------------------------------------------------------
+//write UL gate
+//------------------------------------------------------
+void write_gate(UL_GATE G) {
+  write_symbol(G.symbol);
+}
+
+
+//------------------------------------------------------
+//write UL instance
+//------------------------------------------------------
+void write_instance(UL_INSTANCE I) {
+  printf("<g><title>PART %s</title>\n", encodeText(I.name));
+  write_gate(I.gate);
+  I.texts(T) {write_text(T);}
+  printf("</g>\n");
+}
+
+
+//------------------------------------------------------
+//write UL part
+//------------------------------------------------------
+void write_part(UL_PART P) {
+  P.instances(I) {
+    write_instance(I);
+  }
+}
+
+
+//------------------------------------------------------
+//write UL contact
+//------------------------------------------------------
+void write_contact(UL_CONTACT C) {
+  if (C.pad) {
+    write_pad(C.pad);
+  } else if (C.smd) {
+    write_smd(C.smd);    
+  }
+}
+
+
+//------------------------------------------------------
+//write UL package
+//------------------------------------------------------
+void write_package(UL_PACKAGE PKG) {
+  PKG.polygons(P)   {write_polygon(P);}
+  PKG.circles(C)    {write_circle(C);}
+  PKG.rectangles(R) {write_rectangle(R);}
+  PKG.wires(W)      {write_wire(W);}
+  PKG.texts(T)      {write_text(T);}
+  PKG.contacts(C)   {write_contact(C);}
+  PKG.holes(H)      {write_hole(H);}
+}
+
+
+//------------------------------------------------------
+//write UL element
+//------------------------------------------------------
+void write_element(UL_ELEMENT E) {
+  printf("<g><title>PART %s</title>\n", encodeText(E.name));  
+  E.texts(T) {write_text(T);}
+  write_package(E.package);
+  printf("</g>\n");      
+}
+
+
+//------------------------------------------------------
+//write layer stylesheet to svg file 
+//------------------------------------------------------
+void write_svg_layerStyle (UL_LAYER L) {
+  string color;
+  if (g_monochrome) {
+    color = htmlcolor(0);
+  } else {
+    color = htmlcolor(palette(L.color)&0x00ffffff);
+  }
+  
+  printf ("path.l%d {stroke:%s; fill:none; }\n", L.number, color);
+  printf ("line.l%d {stroke:%s; fill:none; }\n", L.number, color);
+  printf ("circle.l%d {stroke:%s; fill:none; }\n", L.number, color);
+  printf ("circle.j%d {fill:%s; }\n", L.number, color);
+  printf ("rect.l%d {fill:%s; }\n", L.number, color);
+  printf ("text.l%d {font-family:sans-serif; fill:%s; }\n", L.number, color);
+  printf ("polygon.l%d {fill:%s; }\n", L.number, color);
+}
+
+
+void write_sheet_styles() {
+  printf ("<defs>\n");
+  printf ("<style type='text/css'>\n");
+  printf ("<![CDATA[\n");
+  schematic(SCH) {
+    SCH.layers(L) {
+      write_svg_layerStyle(L);
+    }
+  }
+  printf ("]]>\n");
+  printf ("</style>\n");
+  printf ("</defs>\n");
+}
+
+
+void update_used_sheet_layers(UL_SCHEMATIC SCH) {
+  SCH.layers(L) {
+    int used = L.used;
+    if (g_only_visible) {
+      used &= L.visible;
+    }
+    g_used_layers[L.number]=used;    
+  }
+}
+
+                                         
+//------------------------------------------------------
+//write svg header
+//------------------------------------------------------
+void write_sheet_header(UL_SHEET SH) {
+  int t = time();
+  int pageCount = 0;
+  string header =  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+  header += "<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' ";
+  header += "width='%fmm' height='%fmm' viewBox='%f %f %f %f'>\n";
+
+  int dimX    = SH.area.x2-SH.area.x1;
+  int dimY    = SH.area.y2-SH.area.y1;
+  printf(header, u2mm(dimX), u2mm(dimY), u2mm(SH.area.x1), u2mm(-SH.area.y2), u2mm(dimX), u2mm(dimY));
+
+  schematic(SCH) {
+    printf("<title>%s - sheet %d</title>\n", encodeText(SCH.name), SH.number);
+    printf("<desc>generated by eagle2svg %.1f, developed by http://www.nicai-systems.de</desc>\n", VERSION);
+  }
+
+  write_sheet_styles();
+  printf ("<g id='surface0'>\n");
+}
+
+
+//------------------------------------------------------
+//write svg footer
+//------------------------------------------------------
+void write_sheet_footer(UL_SHEET SH) {
+  string footer =  "</g>\n";
+  footer += "</svg>\n";
+  printf(footer);
+}
+
+
+//------------------------------------------------------
+//write whole sheet 
+//------------------------------------------------------
+void write_svg_sheet(string fileName) {
+  output(fileName, "Fwt") {
+    if(sheet) {
+      sheet(SH) {
+        schematic(SCH) {
+          update_used_sheet_layers(SCH);
+        }
+        
+        write_sheet_header(SH);
+        
+        SH.texts(T)      {write_text(T);}
+        SH.wires(W)      {write_wire(W);}        
+        SH.nets(N)       {write_net(N);}
+        SH.busses(B)     {write_bus(B);}
+        SH.rectangles(R) {write_rectangle(R);}
+        SH.polygons(P)   {write_polygon(P);}
+        SH.circles(C)    {write_circle(C);}
+        SH.parts(P)      {write_part(P);}
+
+        write_sheet_footer(SH);
+      }
+    }  
+  }   
+}
+
+
+void update_used_board_layers(UL_BOARD B) {
+  B.layers(L) {
+    int used = L.used;
+    if (g_only_visible) {
+      used &= L.visible;
+    }
+    g_used_layers[L.number]=used;    
+  }
+}
+
+//------------------------------------------------------
+//write svg board styles
+//------------------------------------------------------
+void write_board_styles() {
+  printf ("<defs>\n");
+  printf ("<style type='text/css'>\n");
+  printf ("<![CDATA[\n");
+  board(B) {
+    B.layers(L) {
+      write_svg_layerStyle(L);
+    }
+  }
+  printf ("]]>\n");
+  printf ("</style>\n");
+  printf ("</defs>\n");
+}
+
+
+//------------------------------------------------------
+//write svg board header
+//------------------------------------------------------
+void write_board_header(UL_BOARD B) {
+  int t = time();
+  int pageCount = 0;
+  string header =  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+  header += "<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' ";
+  header += "width='%fmm' height='%fmm' viewBox='%f %f %f %f'>\n";
+
+  int dimX    = B.area.x2-B.area.x1;
+  int dimY    = B.area.y2-B.area.y1;
+  printf(header, u2mm(dimX), u2mm(dimY), u2mm(B.area.x1), u2mm(-B.area.y2), u2mm(dimX), u2mm(dimY));
+
+  printf("<title>%s</title>\n", encodeText(B.name));
+  printf("<desc>generated by eagle2svg %.1f, developed by http://www.nicai-systems.de</desc>\n", VERSION);
+
+  write_board_styles();
+  printf ("<g id='surface0'>\n");
+}
+
+
+//------------------------------------------------------
+//write svg board footer
+//------------------------------------------------------
+void write_board_footer(UL_BOARD B) {
+  string footer =  "</g>\n";
+  footer += "</svg>\n";
+  printf(footer);
+}
+
+
+//------------------------------------------------------
+//write whole board 
+//------------------------------------------------------
+void write_svg_board(string fileName) {
+  output(fileName, "Fwt") {
+    if(board) {
+      board(B) {
+        update_used_board_layers(B);
+        write_board_header(B);
+        
+        B.signals(S)    {write_signal(S);}
+        B.circles(C)    {write_circle(C);}       
+        B.texts(T)      {write_text(T);}
+        B.rectangles(R) {write_rectangle(R);}
+        B.polygons(P)   {write_filled_polygon(P);}
+        B.wires(W)      {write_wire(W);}
+        B.elements(E)   {write_element(E);}
+        B.holes(H)      {write_hole(H);}
+
+        write_board_footer(B);
+      }
+    }  
+  }   
+}
+
+
+//------------------------------------------------------
+// Global mod_ and lib_name
+//------------------------------------------------------
+string sch_name ;   
+
+
+//------------------------------------------------------
+// Select the path where the schematic will be saved 
+//------------------------------------------------------
+void openSchematicPath(string startPath) {
+   string dirName = "";
+   string stringArray[];
+   dirName = dlgDirectory("Select a directory", startPath);
+   
+   if( dirName != "" ) {
+      schematic(S) {
+         int n = 0;
+         string tmpName = S.name; 
+         int nr = strsplit(stringArray, tmpName, '/');
+         sch_name = dirName + "/" + stringArray[nr-1];
+         sch_name = strsub(sch_name , 0, strlen(sch_name) - 4) + ".ps";
+      }
+   }
+}
+
+int displayDialog(string titleStr) {
+  int space = 10;
+  int result = dlgDialog(titleStr) {
+    dlgVBoxLayout {
+      dlgVBoxLayout {
+
+        dlgHBoxLayout dlgSpacing(500);
+        dlgStretch(0);
+        dlgSpacing(space);
+        dlgLabel("Export to file:");
+        dlgStretch(0);
+        dlgHBoxLayout {
+          dlgSpacing(space);
+          dlgStringEdit(sch_name);
+          dlgSpacing(space);
+          dlgPushButton("...") openSchematicPath("C:\\");
+          dlgSpacing(space);
+        }
+        dlgCheckBox("Monochrome", g_monochrome);
+        dlgCheckBox("Only visible", g_only_visible);
+        dlgStretch(10);
+        dlgLabel("developed by <a href='http://www.nicai-systems.de'>http://nibo.nicai-systems.de</a>, based on eagle2ps");
+      }
+      dlgStretch(0);
+      dlgHBoxLayout {
+        dlgStretch(1);
+        dlgPushButton("+OK") dlgAccept();
+        dlgSpacing(space);
+        dlgPushButton("-Cancel") dlgReject();
+        dlgStretch(0);
+        dlgSpacing(space);
+      }
+      dlgStretch(10);
+    }
+  };
+  return result;
+}
+
+
+//------------------------------------------------------
+// main program 
+//------------------------------------------------------
+  string ref;
+  string titleStr;
+
+  sprintf(titleStr, "Export Eagle sheet to SVG, Version: %.1f", VERSION);
+
+  if (schematic) {
+    schematic(S) {
+      sheet(SH) {
+        sprintf(sch_name, "%s_p%d.svg", strsub(S.name, 0, strlen(S.name) - 4), SH.number);
+      }
+    }
+    if(displayDialog(titleStr)) {
+      write_svg_sheet(sch_name);
+    }
+    exit(EXIT_SUCCESS);
+
+  } else if (board) {
+    board(B) {
+      sprintf(sch_name, "%s_brd.svg", strsub(B.name, 0, strlen(B.name) - 4));    
+    }
+    if(displayDialog(titleStr)) {
+      write_svg_board(sch_name);
+    }
+    exit(EXIT_SUCCESS);
+
+  } else {
+    dlgMessageBox("Please run from schematic or board editor." ); 
+    exit(EXIT_FAILURE);
+  }
+