Skip to content

2.1 Part file format

aknoerig edited this page Sep 24, 2014 · 15 revisions

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 pdb folder in the following subfolders:

`pdb/core` FZPs of all parts in the core
`pdb/contrib` FZPs of all parts in the contrib bin
`pdb/obsolete` FZPs of obsolete parts, for backwards compatibility

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

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

Some parts 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 and won't be found in the /pdb or /parts/svg folders. You will also not find your own, custom-created parts in the /parts or /pdb folders. These are stored in your application local storage folder, so that they don’t get lost when you install new versions of Fritzing. The location of this folder differs depending on your operating system, and might even be hidden by default:

Windows Vista/7 `C:\Users\\AppData\Roaming\Fritzing`
Windows XP `C:\Documents and Settings\\Application Data\Fritzing`
Mac OS X `~/.config/Fritzing`
Linux `~/.config/Fritzing`

Inside the application storage area you will find a number of subfolders:

  • 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.
  • Custom part files can be found in the parts folder. Your custom parts are in parts/user (fzp files) and parts/svg/user; imported parts will be in parts/contrib and parts/svg/contrib

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. Once a Fritzing part is in the database, its fzp is stored in the pdb folder (this does not apply to custom parts). New part fzp files are stored in the parts folder, but you can also override the database definition of an exiting part by moving its fzp back into the parts folder. To compile the database run Fritzing from the command line: fritzing.exe -db path/to/parts/parts.db. Once this is complete, all fzps will be moved into the pdb folder.

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 . 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 displayInLabel 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 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 element. So, with the example above, it means that the T1.75_LED.svg file has a number of elements:

  • ...
  • ...
  • ...

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 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 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 the an element in the view's SVG file with a matching id attribute. This 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

In breadboard view, a number of parts feature rubber-band legs (also referred to as bendable legs). Rubber-band legs can be stretched and 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 from the reed switch: Pin 1

Note the legId attribute in the breadboardView element. The legId only works in breadboard view. A single 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 . 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 for additional context): It is something of an art to position the leg element nicely in relation to the connector 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" > Notice how the y2 coordinate for each line extends past the viewBox bottom border at 28.82. Hybrid connectors 'Hybrid' is not a good name. A hybrid connector 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. . 5V@1 I think this mechanism might be unnecessary, and that it would be sufficient to hide the connectors in a given view by assigning them a layer id not visible in that view. In this case setting the layer attribute to 'breadboard' in the schematic and pcb views (and getting rid of the second

element in pcb view) . Internal connections 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: The connectorId attribute refers to the connector id attribute in the 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 We are beginning to add SPICE modeling information to Fritzing parts. The element is a child of the top-level element. Here is an example from a resistor: R{instanceTitle} {net connector0} {net connector1} {resistance} There can be only one element per part, but each element can have multiple elements. One 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 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 elements:
If you have multiple instances of one part in a sketch, then only one set of lines is exported to SPICE (since the rest would be redundant). **Split schematics** This is a new feature which has not yet been rolled out, so there are currently no split-schematic parts shipping with Fritzing. 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 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 element (a child of the top-level 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. The schematic SVG which corresponds to this fzp must use the 3 subpart ids as attributes in elements: and the elements in that SVG must be redistributed to be children of those 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: ... ... ... ... ... **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, and (text flow) elements will not work. Speaking of Illustrator and Inkscape, they both have their idiosyncracies 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 It is better to have 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 In other words, when you are looking at individual SVG elements like or , 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 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 elements in PCB SVGs. Normally, when the gerber exporter sees a 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 element * **id=“nonconn“**. This is also used in elements in PCB SVGs. If you have a element with an id that starts with **nonconn, **then that 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. §§ 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 will with SVG files in this form: §§ 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.