[ell-i-pcb-design] Exporting Eagle schematics to SVG for Github

  • From: Lari Lehtomäki <lari@xxxxxxxxxxxx>
  • To: Otso Jousimaa <otso@xxxxxxxxxxxx>, Teemu Hakala <temmi@xxxxxx>, Pekka Nikander <pekka.nikander@xxxxxx>, Eero Hakala <eero.k.hakala@xxxxxxxxx>, ell-i-pcb-design@xxxxxxxxxxxxx
  • Date: Thu, 30 Oct 2014 14:21:02 +0200

[Forwarding an e-mail from Lari, don't know how this comes through.  --Pekka]

Hello all,

I yesterday proposed that Eagle schematics in Github would also have
jpg/png/pdf version also on Github for us that don't use Eagle. Today
I found that SVG would be even better as Github can show difference
between to SVG-files. Example:

https://github.com/latsku/test-pcb/commit/b201effe8b97be3e1a1701ce5ceeb7290949fc21?short_path=961111f#diff-961111f320480594da2f605f7d2a94b2

You should test 2-up/Swipe/Onion skin below the image. At least for me
the swipe option was most informative.

Exporting SVG-pictures from Eagle is possible with Eagle2SVG plugin
(ULP), which is attached to this email. Original version is on Github:
https://github.com/Rhiath/libraries/blob/master/pcbCreation/eagle2svg-1.1.ulp

I added white background to exported SVG-files compared to original
version of the script.


-- 
Lari Lehtomäki
lari at lehtomaki dot fi
050 320 7920
#usage "<b>Eagle schematic exporting tool  version 1.1 </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 ("svg {background-color: white;\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 ("svg {background-color: white;\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);
  }

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Other related posts:

  • » [ell-i-pcb-design] Exporting Eagle schematics to SVG for Github - Lari Lehtomäki