Skip to content

2.1 Part file format

failiz edited this page Jan 19, 2021 · 15 revisions

Authors: Jonathan Cohen

Introduction

A Fritzing part is made up of a number of files: one required metadata file (file suffix is .fzp, so the metadata file is also referred to as an fzp), and up to four SVG files. We went with multiple image files because each part may appear in four different views (breadboard, schematic, pcb, and Parts Bin icon), often with a different image for each view. We decided not to merge all the SVGs and the metadata together in a single file because keeping them separate makes it easier for different parts to share the same image (for example, many parts share the same pcb footprint), and also because keeping the SVGs in separate files makes it easier to access individual images, e.g., for inspection, or to load into the Parts Editor.

The metadata file lists a part's title, description, and other properties, as well as a references to the part's SVG files. It also specifies a part's connectors and internal buses. Each connector's graphic is an element found in the relevant view SVG file. Since any SVG element can have an id attribute, the metadata file refers to a connector's graphic element using that element's id.

We don't have a schema yet for the FZP, so your best bet is to use an existing FZP file—one from the set of Fritzing core parts—as an example. Start with the smallest simplest ones, and work your way up.

Folder structure

Because of the multitude of files and links between them, the folder structure might seem complicated at first. The metadata files for all the parts that are shipped with Fritzing can be found in the fritzing-parts folder in the following subfolders:

Folder Description
fritzing-parts/core FZPs of all parts in the core
fritzing-parts/contrib FZPs of all parts in the contrib bin
fritzing-parts/obsolete FZPs of obsolete parts, for backwards compatibility

Within the fritzing-parts/svg folder, you will find matching core, contrib and obsolete folders. Within one of these subfolders, the structure is:

Folder Description
fritzing-parts/svg/core/breadboard SVGs for the breadboard view of the core library parts
fritzing-parts/svg/core/icon SVGs for the parts bin icon of the core library parts
fritzing-parts/svg/core/pcb SVGs for the PCB view of the core library parts (aka footprints)
fritzing-parts/svg/core/schematic SVGs for the schematic view of the core library parts (aka schematic symbols)

Since version 0.9.3, the fritzing-parts subfolder is actually a git clone of https://github.com/fritzing/fritzing-parts. Fritzing checks the github repository for updates on every launch, and does a "git pull" if the user agrees.

Some parts however are generated on-the-fly rather than simply loaded, for example, rulers, resistors, pin headers, generic DIPs. Templates for these parts are compiled in with the program.

You will also not find your own, custom-created parts and bins there. These are stored in your Fritzing documents folder, so that they don’t get lost when you install new versions of Fritzing:

Operating System Document folder path
Windows C:\Users\username\Documents\Fritzing\parts
Mac OS X /Users/username/Documents/Fritzing/parts
Linux ~/Documents/Fritzing/parts

Finally, some part-related files are stored in the application storage area, which is usually a hidden folder in your operating system and you shouldn't have to deal with these:

  • The fzz folder contains a folder for each fzz file that is currently open. If there are custom parts in the sketch, the svg and fzp files will be in the fzz folder.
  • The partfactory folder contains files for generated parts, such as pin headers and generic DIPs.
  • Up to version 0.9.2, custom-created parts and bins were also stored here.

The location of this folder depends on the operating system:

Operating System Folder path
Windows Vista and up C:\Users\username\AppData\Roaming\Fritzing
Windows XP C:\Documents and Settings\username\Application Data\Fritzing
Mac OS X ~/.config/Fritzing
Linux ~/.config/Fritzing

You can find the location of a specific part SVG in Fritzing by opening the part in the Parts Editor. Switch to the view you are interested in and choose Show in folder under the File menu.

Fritzing core parts are compiled into a database when Fritzing is shipped--using the data from the fzp files. This database is used for swapping parts (this is a quick mechanism for switching between related parts). The database is an Sqlite file, and the assumption is that it's quicker to load the database than to parse all the part fzp files. To compile the database run Fritzing from the command line: fritzing.exe -db path/to/parts/parts.db or choose Part → Regenerate parts database from the menu.

FZP format

And now to the metafile format. Let's start with a typical example of the first couple of lines:

<?xml version='1.0' encoding='UTF-8'?>
<module moduleId="1a4bfb87a0f0fd2c59be43f3497d72e6" fritzingVersion="0.3.16b.02.24.4002">

After the usual introductory XML boilerplate, the outermost element in an FZP file is always <module>. The moduleId attribute is important—this must be unique across all parts—and Fritzing will reject a part if it has already loaded one with the same moduleId. It would be appropriate to use something like a GUID for the moduleId attribute value though better might be to use the part-type + a GUID. For the fritzingVersion attribute, your best bet is to launch Fritzing and open up the about box, from which you can copy the version string. The first half of the version string is the most important: from the example above that means just the “0.3.16b”.

Next comes:

<author>Stefan Hermann</author>
<version>2</version>
<title>Blue LED - 5mm</title>
<url></url>
<label>LED</label>
<date>2008-10-10</date>
<description>A generic blue LED (~1.8V)</description>
<tags>
    <tag>LED</tag>
    <tag>Blue LED</tag>
    <tag>indicator</tag>
    <tag>fritzing core</tag>
    </tags>

Most of these seem self-explanatory:

  • Obsolete parts use a special version syntax <version replacedby=""> The value of the replacedby attribute is the moduleId of the part which replaces the obsolete part. There are many examples of this in the pdb/obsolete folder. The replacedby attribute can also be applied to individual connectors; see the Connectors section below.
  • The <label> element is the part's default label string when it appears in a Fritzing sketch.
  • The <description> can be plain text or rich text format. Rich text is a subset of html that can be displayed in certain Qt widgets (Qt is Fritzing's underlying GUI framework). If you use rich text, it must be xml-escaped, so the FZPs xml structure doesn't get confused.
  • At present we're not doing much with tags, but in Fritzing you can do a search for parts from the Parts Bin, and the tags are included in that search. You should probably substitute “fritzing user” for “fritzing core” if you are creating a custom part.

Part properties

Now for properties. Here's a sample from a potentiometer:

<properties>
    <property name="family">Potentiometer</property>
    <property name="type">Trimmer Potentiometer</property>
    <property name="Maximum Resistance">10k&#8486;</property>
    <property name="Track">Linear</property>
    <property name="Size">Trimmer - 6mm</property>
</properties>

Properties are important—Fritzing uses them to make it easy to swap between related parts in a sketch. When the properties are loaded, they're stored in a database; searching that database gives a set of related parts. The most important property is the “family”—Fritzing only swaps between parts in the same family. The family property is required: Fritzing will reject parts that don't have a family property.

The values of the other properties are used to populate popup-menus in Fritzing's Inspector window. For example, when you select a potentiometer in a sketch, a popup menu will appear in the Inspector window labeled “type”, with the options “Trimmer Potentiometer”, “Slide Potentiometer”, and “Rotary Shaft Potentiometer”. These values come from several parts in the "potentiometer" family; each part in that family has a different value in the "type" property.

A property may have the attribute showInLabel set to yes, which means that by default, that property should appear when the part's label is visible. For example, the resistor:

    <property name="Resistance" showInLabel="yes">220</property>

Views and layers

Now comes the <views> element which references the SVG files used by the part:

<views>
    <iconView>
    <layers image="icon/LED-blue-5mmicon.svg" >
        <layer layerId="icon" />
    </layers>
</iconView>
<breadboardView fliphorizontal="true" flipvertical="true" >
    <layers image="breadboard/LED-5mm-blue.svg" >
        <layer layerId="breadboard" />
    </layers>
</breadboardView>
<schematicView>
    <layers image="schematic/led.svg" >
        <layer layerId="schematic" />
    </layers>
</schematicView>
<pcbView>
    <layers image="pcb/T1.75_LED.svg" >
        <layer layerId="copper0" />
        <layer layerId="copper1" />
        <layer layerId="silkscreen" />
    </layers>
</pcbView>
</views>

But before diving into details, some explanation is required. Remember that a part generally has a different SVG file for each view. But beyond that, each view has a number of layers. The layers have a particular z-ordering, and from the Fritzing UI a given layer can be set visible or hidden. All part images in Fritzing are assigned to particular layers. Connectors in Fritzing parts can only be assigned to certain layers. Note that in some views, most especially pcb view, a part exists on multiple layers. This doesn't mean the entire part SVG image appears on each of those layers. Rather, internally, the view SVG is split into multiple sub-SVGs, one per layer. The way a given layer is marked in the SVG file is by using the element id attribute again, usually inside a <g> element. So, with the example above, it means that the T1.75_LED.svg file has a number of <g> elements:

  • <g id=”silkscreen”>
  • <g id=”copper0”>
  • <g id=”copper1”>

If a layer is specified in the FZP file, it is very important that an element with that id exists in the SVG file, even if it's only an empty element. At one point we considered having separate SVG files for each layer, but we felt that having more individual files per part would make it more difficult to keep part files organized, and also when creating the SVG image for a view for a given part, having a single SVG would make it much easier to keep the elements on the different layers aligned with each other.

So, back to the sample <view> element, notice that the four views are listed: iconView, breadboardView, schematicView, and pcbView; and notice that there are three layers in PCB view. Something you might overlook the first time through are the flipVertical and flipHorizontal attributes. In Fritzing, the default is that parts in breadboard and pcb view are not flippable, since this usually doesn't correspond well with how you work with real physical parts. By contrast, in schematic view, parts are flippable by default. However, you can enable flipping in any view, and for each of the two axes individually, by setting the corresponding flip- attribute value to “true”.

Through-hole vs. SMD parts

In Fritzing, through-hole parts are defined as those which use both copper0 and copper1 layers; SMD parts use only the copper1 layer. By "use" I mean use in the FZP for <views> and <connectors>, and as element ids in the associated pcb view svg file. If an SMD part is placed onto the bottom layer in Fritzing, the layer is dynamically updated to copper0. Some older THT parts use only the copper0 layer; this is no longer correct, however Fritzing will treat these parts as if both copper0 and copper1 were specified. Note that it is very important that if you specify layers in the FZP, you have matching layers in the relevant SVG (more on this below).

Connectors

Now onto the connectors element:

<connectors>
    <connector type="male" id="connector0" name="cathode" >
        <description>cathode pin</description>
        <views>
            <breadboardView>
                <p svgId="connector0pin" layer="breadboard" terminalId="connector0terminal" />
            </breadboardView>
            <schematicView>
                <p svgId="connector0pin" layer="schematic" terminalId="connector0terminal" />
            </schematicView>
            <pcbView>
                <p svgId="connector0pad" layer="copper0" />
                <p svgId="connector0pad" layer="copper1" />
            </pcbView>
        </views>
    </connector>
    <connector type="male" id="connector1" name="anode" >
        <description>anode pin</description>
        <views>
            <breadboardView>
                <p svgId="connector1pin" layer="breadboard" terminalId="connector1terminal" />
            </breadboardView>
            <schematicView>
                <p svgId="connector1pin" layer="schematic" terminalId="connector1terminal" />
            </schematicView>
            <pcbView>
                <p svgId="connector1pad" layer="copper0" />
                <p svgId="connector1pad" layer="copper1" />
            </pcbView>
        </views>
    </connector>
</connectors>

Connector type only matters in breadboard view, where parts with male connectors can be directly attached to parts with female connectors. In all other views, you must use wires to connect connectors. Parts with female connectors include breadboards and Arduinos, but the great majority of parts have male connectors. Wires have wire type connectors, and SMD parts will usually use pad type connectors.

The <description> element and name attributes seem self-explanatory. But it is important to note that within a part, a connector's name and id attributes must be unique—that is, no two connectors in a given part should have the same id or the same name.

Each connector has sub-elements that reference a particular view. Each sub-element has a layer attribute (at present all parts have all their connectors on a single layer, and it's unlikely that will change).

The svgId attribute refers to an element in the view's SVG file with a matching id attribute. That element defines the shape of the connector and gives its position in the part—it may also define the connector's actual graphic, but that could be elsewhere in the SVG. So in the above example, the “connector0pin” value for the svgId attribute in breadboard view refers to an element in the SVG file LED-5mm-blue.svg:

<rect id="connector0pin" x="4.793" y="65.307" fill="none" width="2.989" height="9.442"/>

The terminalId attribute is optional. Each connector takes up a certain area in a part (in the example above, it's a rectangle), but a wire will actually attach to a connector at a single point within the connector's area. This point of attachment is called a terminal point. The default terminal point is the center of the connector area. If you want the terminal point elsewhere, the terminalId attribute points to yet another element in the SVG file. Here is the SVG element for the terminalId attribute “connector0terminal” in breadboard view:

<rect id="connector0terminal" x="4.793" y="74.192" fill="none" width="2.989" height="0.562"/>

If you use a terminalId attribute in your FZP file, make sure an element with that id really exists in the associated SVG file. Also, although in theory you can name your terminalId attribute anything you want, as long as there's an associated SVG element with that id, in practice we find that it's best to use the connector name followed by “terminal”.

You may recall that an obsolete part can use a replacedby attribute to point to the moduleId of the newer version of the part. Usually, for each connector on the obsolete part, there is a matching connector on the replacement part, and usually the replacement connector has the same id as the obsolete connector, so that it's easy for the software to maintain connections when swapping out an obsolete part. But sometimes the replacement connector does not have the same id. In this case you can use the replacedby attribute on the obsolete connector, with the value being either the id or name of the replacement connector. Here is an example using the name:

<connector id='connector15' name='D0RX' type='female' replacedby='RX/D0'>

Rubber-band legs (optional)

In breadboard view, a number of parts feature rubber-band legs (also referred to as bendable legs). Rubber-band legs can be stretched and have bendpoints added. Legs can use straight lines or bezier curves. From the fzp side, setting this up is pretty straightforward, for example, here is one <connector> from the reed switch:

<connector id="connector0" name="pin 1" type="male">
    <description>Pin 1</description>
    <views>
    <breadboardView>
        <p layer="breadboard" svgId="connector0pin" legId="connector0leg"/>
    </breadboardView>
    <schematicView>
        <p layer="schematic" svgId="connector0pin" terminalId="connector0terminal"/>
    </schematicView>
    <pcbView>
        <p layer="copper0" svgId="connector0pin"/>
        <p layer="copper1" svgId="connector0pin"/>
    </pcbView>
    </views>
</connector>

Note the legId attribute in the breadboardView <layer> element. The legId only works in breadboard view. A single <layer> element may not have a layer both legId and terminalId attributes.

As you probably will have guessed at this point, there must be a corresponding element with id="connector0leg" in the breadboard view SVG for the reed switch. This element should always be a <line>. Of the line's two endpoints, the one that is nearest to the center of the part is treated as the attached end of the leg. The other end of the line is the one that can be dragged. Here is the matching leg from the reed switch (I have included the connector <rect> for additional context):

<rect id="connector0pin" x="0" y="2.937" fill="none" width="1" height="1"/>
<line id="connector0leg" stroke-linecap="round" x1="0" y1="4.062" x2="3" y2="4.062" stroke="#6D6D6D" fill="none" stroke-width="2.5"/>

It is something of an art to position the <line> leg element nicely in relation to the connector <rect> element. There is a leg variant used by a number of parts, such as capacitors and LEDs, in which the leg extends beyond the body of the part. The trick here is to set the draggable endpoint of the line outside the viewBox which defines the rest of the part (some of this will make more sense after you have read the About SVGs section below). Here is an extract of the SVG for a capacitor:

<svg ... width="0.243056in" height="0.400278in" viewBox="0 0 17.5 28.82" >
<g id="breadboard">
    <rect id="connector0pin" x="4.292" y="27.82" fill="none" width="2.083" height="1"/>
    <rect id="connector1pin" x="11.365" y="27.82" fill="none" width="2.275" height="1"/>
    <line id="connector0leg" stroke-linecap="round" x1="5.332" y1="28.82" x2="5.332" y2="49.0" stroke="#8C8C8C" fill="none" stroke-width="2.146" />
    <line id="connector1leg" stroke-linecap="round" x1="12.502" y1="28.82" x2="12.502" y2="49.0" stroke="#8C8C8C" fill="none" stroke-width="2.346" />

Notice how the y2 coordinate for each line extends past the viewBox bottom border at 28.82.

Hybrid connectors (optional)

'Hybrid' is not a good name. A hybrid is a connector that is not visible in certain views. For example there are a number of parts which have prototyping areas in breadboard view that are not visible in other views. There are around a dozen of these--mostly Sparkfun shields--that ship with Fritzing. Another use, is for boards that have internal connections between connectors, where only a single reference is needed on the schematic view (EG GND). A third case, is a board that has header connections on both the top and bottom. The bottom connections need to be shown on the PCB view, but not the top connections.

In each of these situations, the connector definition needs to set the hybrid attribute to 'yes' for each view where the specific connector is NOT to be shown. The layer specified with the hybrid entry must be same as would be used for a non-hybrid connector. That is, the layer must be defined in the <views> information, and it must be a layer that contains connectors. Do not use silkscreen, or an odd layer name to try to separate the hybrid connector pins from the rest of the connection pin graphic elements.

<connector id='connector98' type='female' name='5V@1'>
<description>5V@1</description>
    <views>
        <breadboardView>
            <p layer='breadboard' svgId='connector98pin' />
        </breadboardView>
        <schematicView>
            <p layer='schematic' svgId='connector98pin' terminalId='connector98terminal' hybrid='yes' />
        </schematicView>
        <pcbView>
            <p layer='copper0' svgId='connector98pad' hybrid='yes' />
            <p layer='copper1' svgId='connector98pad' hybrid='yes' />
        </pcbView>
    </views>

A hybrid connector will not be selectable, and will not have any wires (including ratsnest) drawn to it in that view. To make the connector completely invisible, the svg element(s) specified by the xxxId attributes need to be invisible. To arrange that, set the element fill and stroke attribute values to "none". This is one of the cases where is is not sufficient to set the attribute values on a wrapper (parent or ancestor) element. The attributes need to be set directly on the elements with the id attribute that matches the svgId or terminalId from the connector definition. Either the individual "fill" and "stroke" attributes can be used, or they can by combined using the "style" attribute (style="fill:none;stroke:none")

Since the connectors are invisible anyway, the schematic terminalId, and second copper layer have no effect. They can be left out of both the definition and the svg image files. For consistency with other connectors in the same files, they can be left in, as long as svg fill and stroke values are set correctly.

The invisible connector elements can be positioned anywhere (coordinate wise) in the image extents. They can all be placed at the same coordinates, without problems with overlapping wires. No wire ever connects to them, so there is nothing to interfere with.

It is not sufficient to make the view graphic elements invisible and/or move them out of the normal layer (groups). Doing that results in bogus ratsnest lines to the part, when a connection has been defined in another view. Especially when the connector is grouped with other connectors on a bus.

For parts that do not have any schematic or pcb view content, this technique does not work quite as desired. The empty part, and (initially) its part label is still visible in the views, even though there are no connectors. The only way to get around this, seems to be to define the part as belonging to the "breadboard" family.

Internal connections (optional)

A bus is what we call an internal connection between connectors (I don't think this term has this meaning outside of Fritzing). Breadboards and stripboards make heavy use of buses (and with stripboards, the user can change the bus structure dynamically). A number of other parts come with buses, most notably with GND and various ICSP pins on various Arduinos, but also the humble 4-pin pushbutton. The Parts Editor has a 'show internal connections' mode which allows one to visualize and edit buses by treating each of them as a wire. Here's the buses section for the 4-pin pushbutton. Notice there are two separate buses described:

<buses>
    <bus id="bus0" >
        <nodeMember connectorId="connector0" />
        <nodeMember connectorId="connector1" />
    </bus>
    <bus id="bus1" >
        <nodeMember connectorId="connector2" />
        <nodeMember connectorId="connector3" />
    </bus>
</buses>

The connectorId attribute refers to the connector id attribute in the <connectors> element. The bus names are arbitrary, as long as each bus name is unique within a given part (i.e within the fzp file).

SPICE modeling (optional)

We are beginning to add SPICE modeling information to Fritzing parts. The <spice> element is a child of the top-level <module> element. Here is an example from a resistor:

<spice>
    <line>R{instanceTitle} {net connector0} {net connector1} {resistance}</line>
</spice>

There can be only one <spice> element per part, but each element can have multiple <line> elements. One <line> element usually translates into a single line of SPICE output. The items in curly brackets can be thought of as variables which are filled in for each part in the sketch when the SPICE netlist is exported:

  • {instanceTitle} is the a part's label. A resistor label is typically something like R1.
  • {net connector-id} is the SPICE node number to which the named connector is connected
  • {property-name} is the value of the named property. In the above example, {resistance} might be 220 ohms.

If one of the <line> elements contains the SPICE .include command, fritzing will attempt to find that file in the spicemodels subfolder of the Fritzing pdb or parts folder, or in the user local storage parts folder. If the file is found, the contents are pasted into the SPICE output. You may also have multiple <model> elements:

<spice>
    <line … />
    <line … />
    <model … />
    <model … />
</spice>

If you have multiple instances of one part in a sketch, then only one set of <model> lines is exported to SPICE (since the rest would be redundant).

Split schematic symbols (optional)

To explain, let me talk about the lm358 which is an IC that contains a pair of op-amps. Although these two parts are physically adjacent on the chip, conceptually speaking, you might want to use one op-amp in one subcircuit, and the other op-amp in another subcircuit, and if you are drawing this up in schematic view, the two subcircuits might not be located anywhere near each other. If you make some minor modifications to the fzp and schematic svg files, then in schematic view, Fritzing can treat each op-amp on the lm358 as a separate part which can be moved, rotated, flipped independently. The lm358 can in fact be treated as three subparts, two op-amps and a shared power/ground part.

In the fzp, the subparts are defined with a <schematic-subparts> element (a child of the top-level <module> element) which splits up the connectors. Here the power and ground are in subpart1, and the op-amps are in subpart2 and subpart3. The subpart names are arbitrary and must be unique within the part. Each subpart's default label is made up of the part's label concatenated to the subpart label. The lm358's part label is U, so if a particular lm358 has the label U3, then its subparts will be labeled U3_1, U3_2 and U3_3.

<schematic-subparts>
<subpart id="subpart1" label="1">
    <connectors>
        <connector id="connector3"/>
        <connector id="connector7"/>
    </connectors>
</subpart>
<subpart id="subpart2"  label="2">
    <connectors>
        <connector id="connector0"/>
        <connector id="connector1"/>
        <connector id="connector2"/>
    </connectors>
</subpart>
<subpart id="subpart3"  label="3">
    <connectors>
        <connector id="connector4"/>
        <connector id="connector5"/>
        <connector id="connector6"/>
    </connectors>
</subpart>
</schematic-subparts>

The schematic SVG which corresponds to this fzp must use the 3 subpart ids as attributes in <g> elements:

<g id="subpart1">
    <g id="subpart2">
        <g id="subpart3">
        </g>
    </g>
</g>

and the elements in that SVG must be redistributed to be children of those <g> elements. This can take a bit of editing, since the existing schematic SVG may not be organized along these lines, so you end up doing a lot of copy/paste.

FZP structure review

Just for review, here is a high level overview of the structure of every fzp file:

<?xml version='1.0' encoding='UTF-8'?>
<module moduleId="..." fritzingVersion="...">
    <!-- metadata elements like date, author, url etc -->
    <tags>...</tags>
    <properties>...</properties>
    <views>...</views>
    <connectors>...</connectors>
    <buses>...</buses>
    <schematic-subparts>...</schematic-subparts>
</module>

About SVGs

So far, we have mostly been discussing matters from the point of view of the FZP. But there are a few words to add about SVGs. First off, Qt (the framework upon which Fritzing is built) supports a superset of SVG 1.2 Tiny. So, your part image may look great in Illustrator or Inkscape, but Qt won't be able to display it. For example, <tspan> and <flowRoot> (text flow) elements will not work.

Speaking of Illustrator and Inkscape, they both have their idiosyncrasies which sometimes cause problems with Fritzing. One tip with Inkscape is to save your SVGs as “plain SVG” rather than “Inkscape SVG”; this removes a lot of Inkscape-specific elements and attributes. This choice is only available from the “Save As” option in Inkscape. It can also cause problems if you open an Inkscape SVG with Illustrator or vice-versa. Another Inkscape quirk is elements containing internal transforms. Something between Qt and Fritzing code seems to occasionally miss these, so instead of

<circle transform=“translate(23, 34)“ … />

it is better to have

<g transform=“translate(23, 34)“ /><circle … /></g>

The most annoying quirk with Illustrator is that Illustrator defines a pixel (“px”) as 72dpi, whereas in the SVG standard, a “px” is 90dpi. So when you save images from Illustrator, if you want them to show up at the size you expect in Fritzing, save the image in units other than px (and note that if you leave out units entirely, it means "px"). Fritzing does try to correct for this problem, but your safest bet may be to open your Illustrator-based SVG in a text editor and hand-modify the width and height attributes by dividing each by 72 and putting "in" (meaning inches) as the units.

Another really annoying problem with Illustrator is that if it loads an SVG originally created outside of Illustrator, and the SVGs units are not in pixels, then Illustrator does not update any stroke-width attributes when it converts the SVG to pixel units internally. The syndrome that most often results from an unrecalulated stroke-width is an SVG distorted by blobby lines.

Now about measurements and SVGs. One of the pleasures of SVG is that the format can support extremely accurate placement and sizing. At the top level of the SVG, there are three attributes, width, height, and viewBox.  The width and height are real world measurements that can be specified in units such as cm, mm, inches, etc. Illustrator and Inkscape tend to use pixel units, and since this means something different in each program (see above), we would prefer that you change the units in your Fritzing SVGs to cm, mm, or inches. In Inkscape you can set the units in the Document Properties dialog in Inkscape's File menu (but for a more reliable approach see below).

The viewBox attribute defines a rectangle, in arbitrary dimensionless units, which are proportionally related to the width and height. In Fritzing the viewBox attribute is always of the form viewBox="0 0 w h". All the other coordinates in the SVG file (for lines, circles, paths, etc.) are then given relative to w and h.

For example, many Fritzing files use inches as units, and use 1000 dpi as the basis for the viewBox. So you might see something like

<svg width='0.46684in' height='0.20306in' viewBox='0 0 466.84 203.06'>

In other words, when you are looking at individual SVG elements like <rect> or <circle>, their coordinates will be expressed relative to the viewBox and their effective units will be in 1000 per inch increments.

I haven't found a way to reliably set width, height, and viewBox in Inkscape without using the XML editor (under the edit menu) to add/modify the attributes at the top-level svg element.

But once you get those attributes set up, then when you start drawing, all the measurements will be in terms relative to the viewBox--which is proportional to the real-world width and height you've set--so it's therefore possible to position elements with a high level of both precision and accuracy. Coordinates in Fritzing SVG elements should always be unitless, and therefore always refer to the implicit units defined by the viewBox. Inkscape, or maybe it's Illustrator, will usually abide by this stricture, but sometimes <text> element values will be given in px units. Fritzing tries to make a reasonable conversion from these units, but it doesn't always work satisfactorily. Best to convert these to unitless values.

More SVG topics

There are a few Fritzing-specialized SVG attributes:

  • drill=“no“. This is used in <circle> elements in PCB SVGs. Normally, when the gerber exporter sees a <circle> in a copper layer, it will consider it a location for a drill hole. If you are trying to lay down a circular pad, add the attribute drill=“no“ to the <circle> element
  • id=“nonconn“. This is also used in <circle> elements in PCB SVGs. If you have a <circle> element with an id that starts with **nonconn, **then that <circle> is treated as a non-plated hole, possibly with a copper ring if the stroke-width is greater than zero.
  • id=“boardoutline“. This is used for PCB board shapes. A pcb board SVG usually consists of two layers, the board layer and the silkscreen layer (some board SVGs define just the board layer, others define the board layer and both silkscreen top and bottom layers—the board layer is the only required layer). The board layer defines the contour for the layer, but there may also be other graphical elements that you want to appear on the board layer, such as the Arduino alignment marks on an Arduino shield. If there are multiple elements on the board layer, Fritzing will by default choose the one with the largest bounding rect as the board contour. However, if it finds one of the elements has the id boardoutline, then that element will be used as the contour.
  • id=“breadboardbreadboard “. This (along with a postfix of moduleId on the moduleId and the family as breadboard) triggers the breadboard code (always bottom layer, no pcb or schematic) and that is probably the only place it should be used. For through-hole parts, which mostly have exactly the same elements in both copper0 and copper1 layers, it is possible to save repetition by simply making the copper1 element a child of the copper0 element (or vice versa). In fact the current implementation of the Parts Editor will only work with SVG files in this form:
<g id=“copper0“>
    <g id=“copper1“>
        <rects, circles, etc />
    </g>
</g>

The SVG standard gives a default value for most attributes. In particular, Illustrator tends to remove default-valued attributes. Fritzing tries to abide by these defaults, but nevertheless, the unexpected can happen—it is much safer for you to give values for all attributes. For one, missing stroke-width values can be troublesome.

Conclusion

There are more than a thousand parts now shipping with Fritzing. The best way to understand the Fritzing parts format is use these as examples.